Commit b936d54a authored by ibuler's avatar ibuler

[Feature] 添加es支持

parent ba5ab21b
...@@ -60,11 +60,6 @@ class ClusterUpdateView(AdminUserRequiredMixin, SuccessMessageMixin, UpdateView) ...@@ -60,11 +60,6 @@ class ClusterUpdateView(AdminUserRequiredMixin, SuccessMessageMixin, UpdateView)
success_url = reverse_lazy('assets:cluster-list') success_url = reverse_lazy('assets:cluster-list')
success_message = update_success_msg success_message = update_success_msg
def form_valid(self, form):
cluster = form.save(commit=False)
cluster.save()
return super().form_valid(form)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = { context = {
'app': _('assets'), 'app': _('assets'),
......
...@@ -4,7 +4,9 @@ import json ...@@ -4,7 +4,9 @@ import json
from django import forms from django import forms
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.utils.html import escape
from django.db import transaction from django.db import transaction
from django.conf import settings
from .models import Setting from .models import Setting
from .fields import DictField from .fields import DictField
...@@ -30,28 +32,32 @@ def to_form_value(value): ...@@ -30,28 +32,32 @@ def to_form_value(value):
class BaseForm(forms.Form): class BaseForm(forms.Form):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
settings = Setting.objects.all() db_settings = Setting.objects.all()
for name, field in self.fields.items(): for name, field in self.fields.items():
db_value = getattr(settings, name).value db_value = getattr(db_settings, name).value
if db_value: django_value = getattr(settings, name) if hasattr(settings, name) else None
if db_value is not None:
field.initial = to_form_value(db_value) field.initial = to_form_value(db_value)
elif django_value is not None:
field.initial = django_value
def save(self): def save(self, category="default"):
if not self.is_bound: if not self.is_bound:
raise ValueError("Form is not bound") raise ValueError("Form is not bound")
settings = Setting.objects.all() db_settings = Setting.objects.all()
if self.is_valid(): if self.is_valid():
with transaction.atomic(): with transaction.atomic():
for name, value in self.cleaned_data.items(): for name, value in self.cleaned_data.items():
field = self.fields[name] field = self.fields[name]
if isinstance(field.widget, forms.PasswordInput) and not value: if isinstance(field.widget, forms.PasswordInput) and not value:
continue continue
if value == to_form_value(getattr(settings, name).value): if value == to_form_value(getattr(db_settings, name).value):
continue continue
defaults = { defaults = {
'name': name, 'name': name,
'category': category,
'value': to_model_value(value) 'value': to_model_value(value)
} }
Setting.objects.update_or_create(defaults=defaults, name=name) Setting.objects.update_or_create(defaults=defaults, name=name)
...@@ -129,3 +135,28 @@ class LDAPSettingForm(BaseForm): ...@@ -129,3 +135,28 @@ class LDAPSettingForm(BaseForm):
AUTH_LDAP_START_TLS = forms.BooleanField( AUTH_LDAP_START_TLS = forms.BooleanField(
label=_("Use SSL"), initial=False, required=False label=_("Use SSL"), initial=False, required=False
) )
class TerminalSettingForm(BaseForm):
SORT_BY_CHOICES = (
('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 = DictField(
label=_("Command storage"), help_text=_(
"Set terminal storage setting, `default` is the using as default,"
"You can set other storage and some terminal using"
)
)
...@@ -24,6 +24,7 @@ class SettingManager(models.Manager): ...@@ -24,6 +24,7 @@ class SettingManager(models.Manager):
class Setting(models.Model): class Setting(models.Model):
name = models.CharField(max_length=128, unique=True, verbose_name=_("Name")) name = models.CharField(max_length=128, unique=True, verbose_name=_("Name"))
value = models.TextField(verbose_name=_("Value")) value = models.TextField(verbose_name=_("Value"))
category = models.CharField(max_length=128, default="default")
enabled = models.BooleanField(verbose_name=_("Enabled"), default=True) enabled = models.BooleanField(verbose_name=_("Enabled"), default=True)
comment = models.TextField(verbose_name=_("Comment")) comment = models.TextField(verbose_name=_("Comment"))
...@@ -33,12 +34,20 @@ class Setting(models.Model): ...@@ -33,12 +34,20 @@ class Setting(models.Model):
return self.name return self.name
@property @property
def value_(self): def cleaned_value(self):
try: try:
return json.loads(self.value) return json.loads(self.value)
except json.JSONDecodeError: except json.JSONDecodeError:
return None return None
@cleaned_value.setter
def cleaned_value(self, item):
try:
v = json.dumps(item)
self.value = v
except json.JSONDecodeError as e:
raise ValueError("Json dump error: {}".format(str(e)))
@classmethod @classmethod
def refresh_all_settings(cls): def refresh_all_settings(cls):
settings_list = cls.objects.all() settings_list = cls.objects.all()
...@@ -53,9 +62,9 @@ class Setting(models.Model): ...@@ -53,9 +62,9 @@ class Setting(models.Model):
setattr(settings, self.name, value) setattr(settings, self.name, value)
if self.name == "AUTH_LDAP": if self.name == "AUTH_LDAP":
if self.value_ and settings.AUTH_LDAP_BACKEND not in settings.AUTHENTICATION_BACKENDS: if self.cleaned_value and settings.AUTH_LDAP_BACKEND not in settings.AUTHENTICATION_BACKENDS:
settings.AUTHENTICATION_BACKENDS.insert(0, settings.AUTH_LDAP_BACKEND) settings.AUTHENTICATION_BACKENDS.insert(0, settings.AUTH_LDAP_BACKEND)
elif not self.value_ and settings.AUTH_LDAP_BACKEND in settings.AUTHENTICATION_BACKENDS: elif not self.cleaned_value and settings.AUTH_LDAP_BACKEND in settings.AUTHENTICATION_BACKENDS:
settings.AUTHENTICATION_BACKENDS.remove(settings.AUTH_LDAP_BACKEND) settings.AUTHENTICATION_BACKENDS.remove(settings.AUTH_LDAP_BACKEND)
if self.name == "AUTH_LDAP_SEARCH_FILTER": if self.name == "AUTH_LDAP_SEARCH_FILTER":
......
{% extends '_modal.html' %}
{% load i18n %}
{% block modal_id %}add_command_storage_model{% endblock %}
{% block modal_title%}{% trans "Add command storage" %}{% endblock %}
{% block modal_body %}
<form method="post" action="" id="add_command_storage_form">
{% csrf_token %}
<div class="form-group">
<label class="control-label" for="id_assets">{% trans "Template" %}</label>
<a href="{% url 'assets:asset-export' %}" style="display: block">{% trans 'Download' %}</a>
</div>
<div class="form-group">
<label class="control-label" for="id_users">{% trans "Asset csv file" %}</label>
<input id="id_assets" type="file" name="file" />
<span class="help-block red-fonts">
{% trans 'If set id, will use this id update asset existed' %}
</span>
</div>
</form>
{% endblock %}
{% block modal_confirm_id %}btn_asset_import{% endblock %}
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
<a href="{% url 'settings:ldap-setting' %}" class="text-center"><i class="fa fa-archive"></i> {% trans 'LDAP setting' %} </a> <a href="{% url 'settings:ldap-setting' %}" class="text-center"><i class="fa fa-archive"></i> {% trans 'LDAP setting' %} </a>
</li> </li>
<li> <li>
<a href="{% url 'settings:storage-setting' %}" class="text-center"><i class="fa fa-hdd-o"></i> {% trans 'Storage setting' %} </a> <a href="{% url 'settings:terminal-setting' %}" class="text-center"><i class="fa fa-hdd-o"></i> {% trans 'Terminal setting' %} </a>
</li> </li>
</ul> </ul>
</div> </div>
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
<a href="{% url 'settings:ldap-setting' %}" class="text-center"><i class="fa fa-archive"></i> {% trans 'LDAP setting' %} </a> <a href="{% url 'settings:ldap-setting' %}" class="text-center"><i class="fa fa-archive"></i> {% trans 'LDAP setting' %} </a>
</li> </li>
<li> <li>
<a href="{% url 'settings:storage-setting' %}" class="text-center"><i class="fa fa-hdd-o"></i> {% trans 'Storage setting' %} </a> <a href="{% url 'settings:terminal-setting' %}" class="text-center"><i class="fa fa-hdd-o"></i> {% trans 'Terminal setting' %} </a>
</li> </li>
</ul> </ul>
</div> </div>
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
<a href="{% url 'settings:ldap-setting' %}" class="text-center"><i class="fa fa-archive"></i> {% trans 'LDAP setting' %} </a> <a href="{% url 'settings:ldap-setting' %}" class="text-center"><i class="fa fa-archive"></i> {% trans 'LDAP setting' %} </a>
</li> </li>
<li> <li>
<a href="{% url 'settings:storage-setting' %}" class="text-center"><i class="fa fa-hdd-o"></i> {% trans 'Storage setting' %} </a> <a href="{% url 'settings:terminal-setting' %}" class="text-center"><i class="fa fa-hdd-o"></i> {% trans 'Terminal setting' %} </a>
</li> </li>
</ul> </ul>
</div> </div>
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
<a href="{% url 'settings:ldap-setting' %}" class="text-center"><i class="fa fa-archive"></i> {% trans 'LDAP setting' %} </a> <a href="{% url 'settings:ldap-setting' %}" class="text-center"><i class="fa fa-archive"></i> {% trans 'LDAP setting' %} </a>
</li> </li>
<li class="active"> <li class="active">
<a href="{% url 'settings:storage-setting' %}" class="text-center"><i class="fa fa-hdd-o"></i> {% trans 'Storage setting' %} </a> <a href="{% url 'settings:terminal-setting' %}" class="text-center"><i class="fa fa-hdd-o"></i> {% trans 'Terminal setting' %} </a>
</li> </li>
</ul> </ul>
</div> </div>
...@@ -35,26 +35,50 @@ ...@@ -35,26 +35,50 @@
</div> </div>
{% endif %} {% endif %}
{% csrf_token %} {% csrf_token %}
<h3>{% trans "Basic setting" %}</h3>
{% for field in form %}
{% if not field.field|is_bool_field %}
{% bootstrap_field field layout="horizontal" %}
{% else %}
<div class="form-group">
<label for="{{ field.id_for_label }}" class="col-sm-2 control-label">{{ field.label }}</label>
<div class="col-sm-8">
<div class="col-sm-1">
{{ field }}
</div>
<div class="col-sm-9">
<span class="help-block" >{{ field.help_text }}</span>
</div>
</div>
</div>
{% endif %}
{% endfor %}
<div class="hr-line-dashed"></div>
<h3>{% trans "Command storage" %}</h3> <h3>{% trans "Command storage" %}</h3>
<table class="table table-hover " id="task-history-list-table" > <table class="table table-hover " id="task-history-list-table" >
<thead> <thead>
<tr> <tr>
<th>{% trans 'Name' %}</th> <th>{% trans 'Name' %}</th>
<th>{% trans 'Engine' %}</th> <th>{% trans 'Type' %}</th>
<th>{% trans 'Action' %}</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for name, setting in command_storage.items %}
<tr>
<td>{{ name }}</td>
<td>{{ setting.TYPE }}</td>
</tr>
{% endfor %}
</tbody> </tbody>
</table> </table>
{# <button class="btn btn-default btn-circle btn-add-command-storage" data-toggle="modal" data-target="#add_command_storage_model" tabindex="0" type="button"><i class="fa fa-plus"></i></button>#}
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
<h3>{% trans "Replay storage" %}</h3> <h3>{% trans "Replay storage" %}</h3>
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
<div class="form-group"> <div class="form-group">
<div class="col-sm-4 col-sm-offset-2"> <div class="col-sm-4 col-sm-offset-2">
<button class="btn btn-default btn-test" type="button"> {% trans 'Test connection' %}</button>
<button class="btn btn-default" type="reset"> {% trans 'Reset' %}</button> <button class="btn btn-default" type="reset"> {% trans 'Reset' %}</button>
<button id="submit_button" class="btn btn-primary" type="submit">{% trans 'Submit' %}</button> <button id="submit_button" class="btn btn-primary" type="submit">{% trans 'Submit' %}</button>
</div> </div>
...@@ -68,6 +92,7 @@ ...@@ -68,6 +92,7 @@
</div> </div>
</div> </div>
</div> </div>
{% include 'common/_add_terminal_command_storage_modal.html' %}
{% endblock %} {% endblock %}
{% block custom_foot_js %} {% block custom_foot_js %}
<script> <script>
...@@ -97,6 +122,9 @@ $(document).ready(function () { ...@@ -97,6 +122,9 @@ $(document).ready(function () {
success: success, success: success,
error: error error: error
}); });
})
.on('click', '', function () {
}) })
</script> </script>
{% endblock %} {% endblock %}
...@@ -10,5 +10,5 @@ urlpatterns = [ ...@@ -10,5 +10,5 @@ urlpatterns = [
url(r'^$', views.BasicSettingView.as_view(), name='basic-setting'), url(r'^$', views.BasicSettingView.as_view(), name='basic-setting'),
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'^storage/$', views.StorageSettingView.as_view(), name='storage-setting'), url(r'^terminal/$', views.TerminalSettingView.as_view(), name='terminal-setting'),
] ]
from django.views.generic import View, TemplateView from django.views.generic import TemplateView
from django.shortcuts import render, redirect from django.shortcuts import render, redirect
from django.contrib import messages 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 .forms import EmailSettingForm, LDAPSettingForm, BasicSettingForm from .forms import EmailSettingForm, LDAPSettingForm, BasicSettingForm, \
TerminalSettingForm
from .models import Setting from .models import Setting
from .mixins import AdminUserRequiredMixin from .mixins import AdminUserRequiredMixin
from .signals import ldap_auth_enable from .signals import ldap_auth_enable
...@@ -89,27 +91,29 @@ class LDAPSettingView(AdminUserRequiredMixin, TemplateView): ...@@ -89,27 +91,29 @@ class LDAPSettingView(AdminUserRequiredMixin, TemplateView):
return render(request, self.template_name, context) return render(request, self.template_name, context)
class StorageSettingView(AdminUserRequiredMixin, TemplateView): class TerminalSettingView(AdminUserRequiredMixin, TemplateView):
form_class = LDAPSettingForm form_class = TerminalSettingForm
template_name = "common/storage_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
context = { context = {
'app': _('Settings'), 'app': _('Settings'),
'action': _('Storage setting'), 'action': _('Terminal setting'),
'form': self.form_class(), 'form': self.form_class(),
'command_storage': Setting.objects.filter(name__endswith="_COMMAND_STORAGE") 'command_storage': command_storage,
} }
kwargs.update(context) kwargs.update(context)
return super().get_context_data(**kwargs) return super().get_context_data(**kwargs)
def post(self, request): def post(self, request):
print(request.POST)
form = self.form_class(request.POST) form = self.form_class(request.POST)
if form.is_valid(): if form.is_valid():
form.save() form.save()
msg = _("Update setting successfully, please restart program") msg = _("Update setting successfully, please restart program")
messages.success(request, msg) messages.success(request, msg)
return redirect('settings:storage-setting') return redirect('settings:terminal-setting')
else: else:
context = self.get_context_data() context = self.get_context_data()
context.update({"form": form}) context.update({"form": form})
......
...@@ -373,7 +373,23 @@ CAPTCHA_FOREGROUND_COLOR = '#001100' ...@@ -373,7 +373,23 @@ CAPTCHA_FOREGROUND_COLOR = '#001100'
CAPTCHA_NOISE_FUNCTIONS = ('captcha.helpers.noise_dots',) CAPTCHA_NOISE_FUNCTIONS = ('captcha.helpers.noise_dots',)
CAPTCHA_TEST_MODE = CONFIG.CAPTCHA_TEST_MODE CAPTCHA_TEST_MODE = CONFIG.CAPTCHA_TEST_MODE
COMMAND_STORAGE_BACKEND = 'terminal.backends.command.db' COMMAND_STORAGE = {
'ENGINE': 'terminal.backends.command.db',
}
TERMINAL_COMMAND_STORAGE = {
'default': {
'TYPE': 'server',
},
# 'ali-es': {
# 'TYPE': 'elasticsearch',
# 'HOSTS': ['http://elastic:changeme@localhost:9200'],
# },
# 'ali-hz-es': {
# 'TYPE': 'elasticsearch',
# 'HOSTS': ['http://elastic:changeme@localhost:9200'],
# }
}
# Django bootstrap3 setting, more see http://django-bootstrap3.readthedocs.io/en/latest/settings.html # Django bootstrap3 setting, more see http://django-bootstrap3.readthedocs.io/en/latest/settings.html
BOOTSTRAP3 = { BOOTSTRAP3 = {
......
...@@ -21,7 +21,7 @@ from .serializers import TerminalSerializer, StatusSerializer, \ ...@@ -21,7 +21,7 @@ from .serializers import TerminalSerializer, StatusSerializer, \
SessionSerializer, TaskSerializer, ReplaySerializer SessionSerializer, TaskSerializer, ReplaySerializer
from .hands import IsSuperUserOrAppUser, IsAppUser, \ from .hands import IsSuperUserOrAppUser, IsAppUser, \
IsSuperUserOrAppUserOrUserReadonly IsSuperUserOrAppUserOrUserReadonly
from .backends import get_command_store, SessionCommandSerializer from .backends import get_terminal_command_store, SessionCommandSerializer
logger = logging.getLogger(__file__) logger = logging.getLogger(__file__)
...@@ -196,7 +196,7 @@ class CommandViewSet(viewsets.ViewSet): ...@@ -196,7 +196,7 @@ class CommandViewSet(viewsets.ViewSet):
} }
""" """
command_store = get_command_store() command_store = get_terminal_command_store()
serializer_class = SessionCommandSerializer serializer_class = SessionCommandSerializer
permission_classes = (IsSuperUserOrAppUser,) permission_classes = (IsSuperUserOrAppUser,)
...@@ -260,3 +260,10 @@ class SessionReplayViewSet(viewsets.ViewSet): ...@@ -260,3 +260,10 @@ class SessionReplayViewSet(viewsets.ViewSet):
return redirect(url) return redirect(url)
else: else:
return HttpResponseNotFound() return HttpResponseNotFound()
class LoadConfig(APIView):
permission_classes = (IsAppUser,)
def get(self, request):
pass
...@@ -2,9 +2,33 @@ from importlib import import_module ...@@ -2,9 +2,33 @@ 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
TYPE_ENGINE_MAPPING = {
'elasticsearch': 'terminal.backends.command.db',
}
def get_command_store(): def get_command_store():
command_engine = import_module(settings.COMMAND_STORAGE_BACKEND) params = settings.COMMAND_STORAGE
command_store = command_engine.CommandStore() engine_class = import_module(params['ENGINE'])
return command_store storage = engine_class.CommandStore(params)
return storage
def get_terminal_command_store():
storage_list = {}
for name, params in settings.TERMINAL_COMMAND_STORAGE.items():
tp = params['TYPE']
if tp == 'server':
storage = get_command_store()
else:
if not TYPE_ENGINE_MAPPING.get(tp):
raise AssertionError("Command storage type should in {}".format(
', '.join(TYPE_ENGINE_MAPPING.keys()))
)
engine_class = import_module(TYPE_ENGINE_MAPPING[tp])
storage = engine_class.CommandStore(params)
storage_list[name] = storage
return storage_list
...@@ -19,3 +19,9 @@ class CommandBase(object): ...@@ -19,3 +19,9 @@ class CommandBase(object):
input=None, session=None): input=None, session=None):
pass pass
@abc.abstractmethod
def count(self, date_from=None, date_to=None,
user=None, asset=None, system_user=None,
input=None, session=None):
pass
...@@ -8,7 +8,7 @@ from .base import CommandBase ...@@ -8,7 +8,7 @@ from .base import CommandBase
class CommandStore(CommandBase): class CommandStore(CommandBase):
def __init__(self): def __init__(self, params):
from terminal.models import Command from terminal.models import Command
self.model = Command self.model = Command
...@@ -37,7 +37,9 @@ class CommandStore(CommandBase): ...@@ -37,7 +37,9 @@ class CommandStore(CommandBase):
)) ))
return self.model.objects.bulk_create(_commands) return self.model.objects.bulk_create(_commands)
def filter(self, date_from=None, date_to=None, @staticmethod
def make_filter_kwargs(
date_from=None, date_to=None,
user=None, asset=None, system_user=None, user=None, asset=None, system_user=None,
input=None, session=None): input=None, session=None):
filter_kwargs = {} filter_kwargs = {}
...@@ -60,10 +62,28 @@ class CommandStore(CommandBase): ...@@ -60,10 +62,28 @@ class CommandStore(CommandBase):
if session: if session:
filter_kwargs['session'] = session filter_kwargs['session'] = session
return filter_kwargs
def filter(self, date_from=None, date_to=None,
user=None, asset=None, system_user=None,
input=None, session=None):
filter_kwargs = self.make_filter_kwargs(
date_from=date_from, date_to=date_to, user=user,
asset=asset, system_user=system_user, input=input,
session=session,
)
queryset = self.model.objects.filter(**filter_kwargs) queryset = self.model.objects.filter(**filter_kwargs)
return queryset return queryset
def all(self): def count(self, date_from=None, date_to=None,
"""返回所有数据""" user=None, asset=None, system_user=None,
return self.model.objects.iterator() input=None, session=None):
filter_kwargs = self.make_filter_kwargs(
date_from=date_from, date_to=date_to, user=user,
asset=asset, system_user=system_user, input=input,
session=session,
)
count = self.model.objects.filter(**filter_kwargs).count()
return count
...@@ -18,5 +18,20 @@ class AbstractSessionCommand(models.Model): ...@@ -18,5 +18,20 @@ class AbstractSessionCommand(models.Model):
class Meta: class Meta:
abstract = True abstract = True
@classmethod
def from_dict(cls, d):
self = cls()
for k, v in d.items():
setattr(self, k, v)
return self
@classmethod
def from_multi_dict(cls, l):
commands = []
for d in l:
command = cls.from_dict(d)
commands.append(command)
return commands
def __str__(self): def __str__(self):
return self.input return self.input
...@@ -10,7 +10,7 @@ from .models import Terminal ...@@ -10,7 +10,7 @@ from .models import Terminal
class TerminalForm(forms.ModelForm): class TerminalForm(forms.ModelForm):
class Meta: class Meta:
model = Terminal model = Terminal
fields = ['name', 'remote_addr', 'ssh_port', 'http_port', 'comment'] fields = ['name', 'remote_addr', 'ssh_port', 'http_port', 'comment', 'command_storage']
help_texts = { help_texts = {
'ssh_port': _("Coco ssh listen port"), 'ssh_port': _("Coco ssh listen port"),
'http_port': _("Coco http/ws listen port"), 'http_port': _("Coco http/ws listen port"),
......
...@@ -4,17 +4,27 @@ import uuid ...@@ -4,17 +4,27 @@ import uuid
from django.db import models from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.conf import settings
from users.models import User from users.models import User
from .backends.command.models import AbstractSessionCommand from .backends.command.models import AbstractSessionCommand
def get_all_command_storage():
storage_choices = []
for k, v in settings.TERMINAL_COMMAND_STORAGE.items():
storage_choices.append((k, k))
return storage_choices
class Terminal(models.Model): class Terminal(models.Model):
id = models.UUIDField(default=uuid.uuid4, primary_key=True) id = models.UUIDField(default=uuid.uuid4, primary_key=True)
name = models.CharField(max_length=32, verbose_name=_('Name')) name = models.CharField(max_length=32, verbose_name=_('Name'))
remote_addr = models.CharField(max_length=128, verbose_name=_('Remote Address')) remote_addr = models.CharField(max_length=128, verbose_name=_('Remote Address'))
ssh_port = models.IntegerField(verbose_name=_('SSH Port'), default=2222) ssh_port = models.IntegerField(verbose_name=_('SSH Port'), default=2222)
http_port = models.IntegerField(verbose_name=_('HTTP Port'), default=5000) http_port = models.IntegerField(verbose_name=_('HTTP Port'), default=5000)
command_storage = models.CharField(max_length=128, verbose_name=_("Command storage"), default='default', choices=get_all_command_storage())
replay_storage = models.CharField(max_length=128, verbose_name=_("Replay storage"), default='default')
user = models.OneToOneField(User, related_name='terminal', verbose_name='Application User', null=True, on_delete=models.CASCADE) user = models.OneToOneField(User, related_name='terminal', verbose_name='Application User', null=True, on_delete=models.CASCADE)
is_accepted = models.BooleanField(default=False, verbose_name='Is Accepted') is_accepted = models.BooleanField(default=False, verbose_name='Is Accepted')
is_deleted = models.BooleanField(default=False) is_deleted = models.BooleanField(default=False)
...@@ -33,6 +43,16 @@ class Terminal(models.Model): ...@@ -33,6 +43,16 @@ class Terminal(models.Model):
self.user.is_active = active self.user.is_active = active
self.user.save() self.user.save()
def get_common_storage(self):
pass
def get_replay_storage(self):
pass
@property
def config(self):
return
def create_app_user(self): def create_app_user(self):
random = uuid.uuid4().hex[:6] random = uuid.uuid4().hex[:6]
user, access_key = User.create_app_user(name="{}-{}".format(self.name, random), comment=self.comment) user, access_key = User.create_app_user(name="{}-{}".format(self.name, random), comment=self.comment)
......
...@@ -5,7 +5,7 @@ from django.utils import timezone ...@@ -5,7 +5,7 @@ from django.utils import timezone
from rest_framework import serializers from rest_framework import serializers
from .models import Terminal, Status, Session, Task from .models import Terminal, Status, Session, Task
from .backends import get_command_store from .backends import get_terminal_command_store
class TerminalSerializer(serializers.ModelSerializer): class TerminalSerializer(serializers.ModelSerializer):
...@@ -43,7 +43,7 @@ class TerminalSerializer(serializers.ModelSerializer): ...@@ -43,7 +43,7 @@ class TerminalSerializer(serializers.ModelSerializer):
class SessionSerializer(serializers.ModelSerializer): class SessionSerializer(serializers.ModelSerializer):
command_amount = serializers.SerializerMethodField() command_amount = serializers.SerializerMethodField()
command_store = get_command_store() command_store = get_terminal_command_store()
class Meta: class Meta:
model = Session model = Session
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
{% bootstrap_field form.remote_addr layout="horizontal" %} {% bootstrap_field form.remote_addr layout="horizontal" %}
{% bootstrap_field form.ssh_port layout="horizontal" %} {% bootstrap_field form.ssh_port layout="horizontal" %}
{% bootstrap_field form.http_port layout="horizontal" %} {% bootstrap_field form.http_port layout="horizontal" %}
{% bootstrap_field form.command_storage layout="horizontal" %}
{% bootstrap_field form.comment layout="horizontal" %} {% bootstrap_field form.comment layout="horizontal" %}
</form> </form>
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
{% bootstrap_field form.remote_addr layout="horizontal" %} {% bootstrap_field form.remote_addr layout="horizontal" %}
{% bootstrap_field form.ssh_port layout="horizontal" %} {% bootstrap_field form.ssh_port layout="horizontal" %}
{% bootstrap_field form.http_port layout="horizontal" %} {% bootstrap_field form.http_port layout="horizontal" %}
{% bootstrap_field form.command_storage layout="horizontal" %}
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
<h3>{% trans 'Other' %}</h3> <h3>{% trans 'Other' %}</h3>
......
# ~*~ coding: utf-8 ~*~ # ~*~ coding: utf-8 ~*~
from django import template from django import template
from ..backends import get_command_store from ..backends import get_terminal_command_store
register = template.Library() register = template.Library()
command_store = get_command_store() command_store_dict = get_terminal_command_store()
@register.filter @register.filter
def get_session_command_amount(session_id): def get_session_command_amount(session_id):
return len(command_store.filter(session=str(session_id))) amount = 0
for name, store in command_store_dict.items():
amount += store.count(session=str(session_id))
return amount
...@@ -9,10 +9,10 @@ from django.utils.translation import ugettext as _ ...@@ -9,10 +9,10 @@ from django.utils.translation import ugettext as _
from common.mixins import DatetimeSearchMixin from common.mixins import DatetimeSearchMixin
from ..models import Command from ..models import Command
from .. import utils from .. import utils
from ..backends import get_command_store from ..backends import get_terminal_command_store
__all__ = ['CommandListView'] __all__ = ['CommandListView']
command_store = get_command_store() command_store_list = get_terminal_command_store()
class CommandListView(DatetimeSearchMixin, ListView): class CommandListView(DatetimeSearchMixin, ListView):
...@@ -39,7 +39,10 @@ class CommandListView(DatetimeSearchMixin, ListView): ...@@ -39,7 +39,10 @@ class CommandListView(DatetimeSearchMixin, ListView):
filter_kwargs['system_user'] = self.system_user filter_kwargs['system_user'] = self.system_user
if self.command: if self.command:
filter_kwargs['input'] = self.command filter_kwargs['input'] = self.command
queryset = command_store.filter(**filter_kwargs) queryset = []
for store in command_store_list:
queryset.extend(store.filter(**filter_kwargs))
queryset = sorted(queryset, key=lambda c: c.timestamp, reverse=True)
return queryset return queryset
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
......
...@@ -10,7 +10,7 @@ from django.conf import settings ...@@ -10,7 +10,7 @@ from django.conf import settings
from users.utils import AdminUserRequiredMixin from users.utils import AdminUserRequiredMixin
from common.mixins import DatetimeSearchMixin from common.mixins import DatetimeSearchMixin
from ..models import Session, Command, Terminal from ..models import Session, Command, Terminal
from ..backends import get_command_store from ..backends import get_terminal_command_store
from .. import utils from .. import utils
...@@ -19,7 +19,7 @@ __all__ = [ ...@@ -19,7 +19,7 @@ __all__ = [
'SessionDetailView', 'SessionDetailView',
] ]
command_store = get_command_store() command_store = get_terminal_command_store()
class SessionListView(AdminUserRequiredMixin, DatetimeSearchMixin, ListView): class SessionListView(AdminUserRequiredMixin, DatetimeSearchMixin, ListView):
......
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