From b936d54a4883782bcd5f2db779c9441dd5c49193 Mon Sep 17 00:00:00 2001 From: ibuler Date: Sat, 20 Jan 2018 22:22:09 +0800 Subject: [PATCH] =?UTF-8?q?[Feature]=20=E6=B7=BB=E5=8A=A0es=E6=94=AF?= =?UTF-8?q?=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/views/cluster.py | 5 --- apps/common/forms.py | 43 ++++++++++++++++--- apps/common/models.py | 15 +++++-- .../_add_terminal_command_storage_modal.html | 21 +++++++++ .../templates/common/basic_setting.html | 2 +- .../templates/common/email_setting.html | 2 +- .../common/templates/common/ldap_setting.html | 2 +- ...age_setting.html => terminal_setting.html} | 38 +++++++++++++--- apps/common/urls/view_urls.py | 2 +- apps/common/views.py | 20 +++++---- apps/jumpserver/settings.py | 18 +++++++- apps/terminal/api.py | 11 ++++- apps/terminal/backends/__init__.py | 30 +++++++++++-- apps/terminal/backends/command/base.py | 6 +++ apps/terminal/backends/command/db.py | 34 ++++++++++++--- apps/terminal/backends/command/models.py | 15 +++++++ apps/terminal/forms.py | 2 +- apps/terminal/models.py | 20 +++++++++ apps/terminal/serializers.py | 4 +- .../terminal/terminal_modal_accept.html | 1 + .../templates/terminal/terminal_update.html | 1 + apps/terminal/templatetags/terminal_tags.py | 10 +++-- apps/terminal/views/command.py | 9 ++-- apps/terminal/views/session.py | 4 +- 24 files changed, 259 insertions(+), 56 deletions(-) create mode 100644 apps/common/templates/common/_add_terminal_command_storage_modal.html rename apps/common/templates/common/{storage_setting.html => terminal_setting.html} (63%) diff --git a/apps/assets/views/cluster.py b/apps/assets/views/cluster.py index 835229fc1..5df58953c 100644 --- a/apps/assets/views/cluster.py +++ b/apps/assets/views/cluster.py @@ -60,11 +60,6 @@ class ClusterUpdateView(AdminUserRequiredMixin, SuccessMessageMixin, UpdateView) success_url = reverse_lazy('assets:cluster-list') 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): context = { 'app': _('assets'), diff --git a/apps/common/forms.py b/apps/common/forms.py index 073bb671f..ab3dadba3 100644 --- a/apps/common/forms.py +++ b/apps/common/forms.py @@ -4,7 +4,9 @@ import json from django import forms from django.utils.translation import ugettext_lazy as _ +from django.utils.html import escape from django.db import transaction +from django.conf import settings from .models import Setting from .fields import DictField @@ -30,28 +32,32 @@ def to_form_value(value): class BaseForm(forms.Form): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - settings = Setting.objects.all() + db_settings = Setting.objects.all() for name, field in self.fields.items(): - db_value = getattr(settings, name).value - if db_value: + db_value = getattr(db_settings, name).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) + elif django_value is not None: + field.initial = django_value - def save(self): + def save(self, category="default"): if not self.is_bound: raise ValueError("Form is not bound") - settings = Setting.objects.all() + db_settings = Setting.objects.all() if self.is_valid(): with transaction.atomic(): for name, value in self.cleaned_data.items(): field = self.fields[name] if isinstance(field.widget, forms.PasswordInput) and not value: continue - if value == to_form_value(getattr(settings, name).value): + if value == to_form_value(getattr(db_settings, name).value): continue defaults = { 'name': name, + 'category': category, 'value': to_model_value(value) } Setting.objects.update_or_create(defaults=defaults, name=name) @@ -129,3 +135,28 @@ class LDAPSettingForm(BaseForm): AUTH_LDAP_START_TLS = forms.BooleanField( 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" + ) + ) diff --git a/apps/common/models.py b/apps/common/models.py index 091b8b83a..afee1e13d 100644 --- a/apps/common/models.py +++ b/apps/common/models.py @@ -24,6 +24,7 @@ class SettingManager(models.Manager): class Setting(models.Model): name = models.CharField(max_length=128, unique=True, verbose_name=_("Name")) value = models.TextField(verbose_name=_("Value")) + category = models.CharField(max_length=128, default="default") enabled = models.BooleanField(verbose_name=_("Enabled"), default=True) comment = models.TextField(verbose_name=_("Comment")) @@ -33,12 +34,20 @@ class Setting(models.Model): return self.name @property - def value_(self): + def cleaned_value(self): try: return json.loads(self.value) except json.JSONDecodeError: 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 def refresh_all_settings(cls): settings_list = cls.objects.all() @@ -53,9 +62,9 @@ class Setting(models.Model): setattr(settings, self.name, value) 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) - 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) if self.name == "AUTH_LDAP_SEARCH_FILTER": diff --git a/apps/common/templates/common/_add_terminal_command_storage_modal.html b/apps/common/templates/common/_add_terminal_command_storage_modal.html new file mode 100644 index 000000000..678152981 --- /dev/null +++ b/apps/common/templates/common/_add_terminal_command_storage_modal.html @@ -0,0 +1,21 @@ +{% extends '_modal.html' %} +{% load i18n %} +{% block modal_id %}add_command_storage_model{% endblock %} +{% block modal_title%}{% trans "Add command storage" %}{% endblock %} +{% block modal_body %} +
+ {% csrf_token %} +
+ + {% trans 'Download' %} +
+
+ + + + {% trans 'If set id, will use this id update asset existed' %} + +
+
+{% endblock %} +{% block modal_confirm_id %}btn_asset_import{% endblock %} diff --git a/apps/common/templates/common/basic_setting.html b/apps/common/templates/common/basic_setting.html index 9d67d762d..496eca977 100644 --- a/apps/common/templates/common/basic_setting.html +++ b/apps/common/templates/common/basic_setting.html @@ -21,7 +21,7 @@ {% trans 'LDAP setting' %}
  • - {% trans 'Storage setting' %} + {% trans 'Terminal setting' %}
  • diff --git a/apps/common/templates/common/email_setting.html b/apps/common/templates/common/email_setting.html index 2cd018021..1fd772db1 100644 --- a/apps/common/templates/common/email_setting.html +++ b/apps/common/templates/common/email_setting.html @@ -21,7 +21,7 @@ {% trans 'LDAP setting' %}
  • - {% trans 'Storage setting' %} + {% trans 'Terminal setting' %}
  • diff --git a/apps/common/templates/common/ldap_setting.html b/apps/common/templates/common/ldap_setting.html index de4a196c9..f0569f873 100644 --- a/apps/common/templates/common/ldap_setting.html +++ b/apps/common/templates/common/ldap_setting.html @@ -21,7 +21,7 @@ {% trans 'LDAP setting' %}
  • - {% trans 'Storage setting' %} + {% trans 'Terminal setting' %}
  • diff --git a/apps/common/templates/common/storage_setting.html b/apps/common/templates/common/terminal_setting.html similarity index 63% rename from apps/common/templates/common/storage_setting.html rename to apps/common/templates/common/terminal_setting.html index cf2c243f1..3d0b7eb6f 100644 --- a/apps/common/templates/common/storage_setting.html +++ b/apps/common/templates/common/terminal_setting.html @@ -21,7 +21,7 @@ {% trans 'LDAP setting' %}
  • - {% trans 'Storage setting' %} + {% trans 'Terminal setting' %}
  • @@ -35,26 +35,50 @@ {% endif %} {% csrf_token %} +

    {% trans "Basic setting" %}

    + {% for field in form %} + {% if not field.field|is_bool_field %} + {% bootstrap_field field layout="horizontal" %} + {% else %} +
    + +
    +
    + {{ field }} +
    +
    + {{ field.help_text }} +
    +
    +
    + {% endif %} + {% endfor %} + +

    {% trans "Command storage" %}

    - - + + {% for name, setting in command_storage.items %} + + + + + {% endfor %}
    {% trans 'Name' %}{% trans 'Engine' %}{% trans 'Action' %}{% trans 'Type' %}
    {{ name }}{{ setting.TYPE }}
    - +{# #}

    {% trans "Replay storage" %}

    -
    @@ -68,6 +92,7 @@
    + {% include 'common/_add_terminal_command_storage_modal.html' %} {% endblock %} {% block custom_foot_js %} {% endblock %} diff --git a/apps/common/urls/view_urls.py b/apps/common/urls/view_urls.py index 57594b043..466f7c49c 100644 --- a/apps/common/urls/view_urls.py +++ b/apps/common/urls/view_urls.py @@ -10,5 +10,5 @@ urlpatterns = [ url(r'^$', views.BasicSettingView.as_view(), name='basic-setting'), url(r'^email/$', views.EmailSettingView.as_view(), name='email-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'), ] diff --git a/apps/common/views.py b/apps/common/views.py index 6ab46ead4..8e7dc8341 100644 --- a/apps/common/views.py +++ b/apps/common/views.py @@ -1,9 +1,11 @@ -from django.views.generic import View, TemplateView +from django.views.generic import TemplateView from django.shortcuts import render, redirect from django.contrib import messages 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 .mixins import AdminUserRequiredMixin from .signals import ldap_auth_enable @@ -89,27 +91,29 @@ class LDAPSettingView(AdminUserRequiredMixin, TemplateView): return render(request, self.template_name, context) -class StorageSettingView(AdminUserRequiredMixin, TemplateView): - form_class = LDAPSettingForm - template_name = "common/storage_setting.html" +class TerminalSettingView(AdminUserRequiredMixin, TemplateView): + form_class = TerminalSettingForm + template_name = "common/terminal_setting.html" def get_context_data(self, **kwargs): + command_storage = settings.TERMINAL_COMMAND_STORAGE context = { 'app': _('Settings'), - 'action': _('Storage setting'), + 'action': _('Terminal setting'), 'form': self.form_class(), - 'command_storage': Setting.objects.filter(name__endswith="_COMMAND_STORAGE") + 'command_storage': command_storage, } kwargs.update(context) return super().get_context_data(**kwargs) def post(self, request): + print(request.POST) form = self.form_class(request.POST) if form.is_valid(): form.save() msg = _("Update setting successfully, please restart program") messages.success(request, msg) - return redirect('settings:storage-setting') + return redirect('settings:terminal-setting') else: context = self.get_context_data() context.update({"form": form}) diff --git a/apps/jumpserver/settings.py b/apps/jumpserver/settings.py index 7a8aa422e..d023b587a 100644 --- a/apps/jumpserver/settings.py +++ b/apps/jumpserver/settings.py @@ -373,7 +373,23 @@ CAPTCHA_FOREGROUND_COLOR = '#001100' CAPTCHA_NOISE_FUNCTIONS = ('captcha.helpers.noise_dots',) 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 BOOTSTRAP3 = { diff --git a/apps/terminal/api.py b/apps/terminal/api.py index 87311d5b2..e587d8928 100644 --- a/apps/terminal/api.py +++ b/apps/terminal/api.py @@ -21,7 +21,7 @@ from .serializers import TerminalSerializer, StatusSerializer, \ SessionSerializer, TaskSerializer, ReplaySerializer from .hands import IsSuperUserOrAppUser, IsAppUser, \ IsSuperUserOrAppUserOrUserReadonly -from .backends import get_command_store, SessionCommandSerializer +from .backends import get_terminal_command_store, SessionCommandSerializer logger = logging.getLogger(__file__) @@ -196,7 +196,7 @@ class CommandViewSet(viewsets.ViewSet): } """ - command_store = get_command_store() + command_store = get_terminal_command_store() serializer_class = SessionCommandSerializer permission_classes = (IsSuperUserOrAppUser,) @@ -260,3 +260,10 @@ class SessionReplayViewSet(viewsets.ViewSet): return redirect(url) else: return HttpResponseNotFound() + + +class LoadConfig(APIView): + permission_classes = (IsAppUser,) + + def get(self, request): + pass diff --git a/apps/terminal/backends/__init__.py b/apps/terminal/backends/__init__.py index 6baaed3c4..8b09f0c55 100644 --- a/apps/terminal/backends/__init__.py +++ b/apps/terminal/backends/__init__.py @@ -2,9 +2,33 @@ from importlib import import_module from django.conf import settings from .command.serializers import SessionCommandSerializer +TYPE_ENGINE_MAPPING = { + 'elasticsearch': 'terminal.backends.command.db', +} + def get_command_store(): - command_engine = import_module(settings.COMMAND_STORAGE_BACKEND) - command_store = command_engine.CommandStore() - return command_store + params = settings.COMMAND_STORAGE + engine_class = import_module(params['ENGINE']) + 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 + + diff --git a/apps/terminal/backends/command/base.py b/apps/terminal/backends/command/base.py index 0aa689738..585930a5d 100644 --- a/apps/terminal/backends/command/base.py +++ b/apps/terminal/backends/command/base.py @@ -19,3 +19,9 @@ class CommandBase(object): input=None, session=None): pass + @abc.abstractmethod + def count(self, date_from=None, date_to=None, + user=None, asset=None, system_user=None, + input=None, session=None): + pass + diff --git a/apps/terminal/backends/command/db.py b/apps/terminal/backends/command/db.py index 27ee19a14..85b99ce80 100644 --- a/apps/terminal/backends/command/db.py +++ b/apps/terminal/backends/command/db.py @@ -8,7 +8,7 @@ from .base import CommandBase class CommandStore(CommandBase): - def __init__(self): + def __init__(self, params): from terminal.models import Command self.model = Command @@ -37,9 +37,11 @@ class CommandStore(CommandBase): )) return self.model.objects.bulk_create(_commands) - def filter(self, date_from=None, date_to=None, - user=None, asset=None, system_user=None, - input=None, session=None): + @staticmethod + def make_filter_kwargs( + date_from=None, date_to=None, + user=None, asset=None, system_user=None, + input=None, session=None): filter_kwargs = {} date_from_default = timezone.now() - datetime.timedelta(days=7) date_to_default = timezone.now() @@ -60,10 +62,28 @@ class CommandStore(CommandBase): if 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) return queryset - def all(self): - """返回所有数据""" - return self.model.objects.iterator() + def count(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, + ) + count = self.model.objects.filter(**filter_kwargs).count() + return count + diff --git a/apps/terminal/backends/command/models.py b/apps/terminal/backends/command/models.py index 2d1387427..cc0d375e6 100644 --- a/apps/terminal/backends/command/models.py +++ b/apps/terminal/backends/command/models.py @@ -18,5 +18,20 @@ class AbstractSessionCommand(models.Model): class Meta: 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): return self.input diff --git a/apps/terminal/forms.py b/apps/terminal/forms.py index 5b6278c02..4253da70a 100644 --- a/apps/terminal/forms.py +++ b/apps/terminal/forms.py @@ -10,7 +10,7 @@ from .models import Terminal class TerminalForm(forms.ModelForm): class Meta: model = Terminal - fields = ['name', 'remote_addr', 'ssh_port', 'http_port', 'comment'] + fields = ['name', 'remote_addr', 'ssh_port', 'http_port', 'comment', 'command_storage'] help_texts = { 'ssh_port': _("Coco ssh listen port"), 'http_port': _("Coco http/ws listen port"), diff --git a/apps/terminal/models.py b/apps/terminal/models.py index f545baa5f..b8524f727 100644 --- a/apps/terminal/models.py +++ b/apps/terminal/models.py @@ -4,17 +4,27 @@ import uuid from django.db import models from django.utils.translation import ugettext_lazy as _ +from django.conf import settings from users.models import User 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): id = models.UUIDField(default=uuid.uuid4, primary_key=True) name = models.CharField(max_length=32, verbose_name=_('Name')) remote_addr = models.CharField(max_length=128, verbose_name=_('Remote Address')) ssh_port = models.IntegerField(verbose_name=_('SSH Port'), default=2222) 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) is_accepted = models.BooleanField(default=False, verbose_name='Is Accepted') is_deleted = models.BooleanField(default=False) @@ -33,6 +43,16 @@ class Terminal(models.Model): self.user.is_active = active 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): random = uuid.uuid4().hex[:6] user, access_key = User.create_app_user(name="{}-{}".format(self.name, random), comment=self.comment) diff --git a/apps/terminal/serializers.py b/apps/terminal/serializers.py index 52b4d2b3c..ecea7edfd 100644 --- a/apps/terminal/serializers.py +++ b/apps/terminal/serializers.py @@ -5,7 +5,7 @@ from django.utils import timezone from rest_framework import serializers from .models import Terminal, Status, Session, Task -from .backends import get_command_store +from .backends import get_terminal_command_store class TerminalSerializer(serializers.ModelSerializer): @@ -43,7 +43,7 @@ class TerminalSerializer(serializers.ModelSerializer): class SessionSerializer(serializers.ModelSerializer): command_amount = serializers.SerializerMethodField() - command_store = get_command_store() + command_store = get_terminal_command_store() class Meta: model = Session diff --git a/apps/terminal/templates/terminal/terminal_modal_accept.html b/apps/terminal/templates/terminal/terminal_modal_accept.html index b4a18b17c..fe70bb342 100644 --- a/apps/terminal/templates/terminal/terminal_modal_accept.html +++ b/apps/terminal/templates/terminal/terminal_modal_accept.html @@ -12,6 +12,7 @@ {% bootstrap_field form.remote_addr layout="horizontal" %} {% bootstrap_field form.ssh_port layout="horizontal" %} {% bootstrap_field form.http_port layout="horizontal" %} + {% bootstrap_field form.command_storage layout="horizontal" %} {% bootstrap_field form.comment layout="horizontal" %} diff --git a/apps/terminal/templates/terminal/terminal_update.html b/apps/terminal/templates/terminal/terminal_update.html index 9ebd9d2d8..cbf745608 100644 --- a/apps/terminal/templates/terminal/terminal_update.html +++ b/apps/terminal/templates/terminal/terminal_update.html @@ -35,6 +35,7 @@ {% bootstrap_field form.remote_addr layout="horizontal" %} {% bootstrap_field form.ssh_port layout="horizontal" %} {% bootstrap_field form.http_port layout="horizontal" %} + {% bootstrap_field form.command_storage layout="horizontal" %}

    {% trans 'Other' %}

    diff --git a/apps/terminal/templatetags/terminal_tags.py b/apps/terminal/templatetags/terminal_tags.py index 22b517880..72822b00a 100644 --- a/apps/terminal/templatetags/terminal_tags.py +++ b/apps/terminal/templatetags/terminal_tags.py @@ -1,13 +1,15 @@ # ~*~ coding: utf-8 ~*~ from django import template -from ..backends import get_command_store +from ..backends import get_terminal_command_store register = template.Library() -command_store = get_command_store() +command_store_dict = get_terminal_command_store() @register.filter 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 diff --git a/apps/terminal/views/command.py b/apps/terminal/views/command.py index 8b0479d3e..79b2eb2cc 100644 --- a/apps/terminal/views/command.py +++ b/apps/terminal/views/command.py @@ -9,10 +9,10 @@ from django.utils.translation import ugettext as _ from common.mixins import DatetimeSearchMixin from ..models import Command from .. import utils -from ..backends import get_command_store +from ..backends import get_terminal_command_store __all__ = ['CommandListView'] -command_store = get_command_store() +command_store_list = get_terminal_command_store() class CommandListView(DatetimeSearchMixin, ListView): @@ -39,7 +39,10 @@ class CommandListView(DatetimeSearchMixin, ListView): filter_kwargs['system_user'] = self.system_user if 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 def get_context_data(self, **kwargs): diff --git a/apps/terminal/views/session.py b/apps/terminal/views/session.py index 22d04fbaf..63fcf5eb7 100644 --- a/apps/terminal/views/session.py +++ b/apps/terminal/views/session.py @@ -10,7 +10,7 @@ from django.conf import settings from users.utils import AdminUserRequiredMixin from common.mixins import DatetimeSearchMixin from ..models import Session, Command, Terminal -from ..backends import get_command_store +from ..backends import get_terminal_command_store from .. import utils @@ -19,7 +19,7 @@ __all__ = [ 'SessionDetailView', ] -command_store = get_command_store() +command_store = get_terminal_command_store() class SessionListView(AdminUserRequiredMixin, DatetimeSearchMixin, ListView): -- GitLab