diff --git a/apps/__init__.py b/apps/__init__.py index a9954fbdc..e8c9d2d6e 100644 --- a/apps/__init__.py +++ b/apps/__init__.py @@ -2,4 +2,4 @@ # -*- coding: utf-8 -*- # -__version__ = "1.4.1" +__version__ = "1.4.3" diff --git a/apps/assets/api/__init__.py b/apps/assets/api/__init__.py index a1a3beee7..1d7dbca00 100644 --- a/apps/assets/api/__init__.py +++ b/apps/assets/api/__init__.py @@ -4,3 +4,4 @@ from .label import * from .system_user import * from .node import * from .domain import * +from .cmd_filter import * diff --git a/apps/assets/api/cmd_filter.py b/apps/assets/api/cmd_filter.py new file mode 100644 index 000000000..f4537cf17 --- /dev/null +++ b/apps/assets/api/cmd_filter.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +# + +from rest_framework_bulk import BulkModelViewSet +from django.shortcuts import get_object_or_404 + +from ..hands import IsOrgAdmin +from ..models import CommandFilter, CommandFilterRule +from .. import serializers + + +__all__ = ['CommandFilterViewSet', 'CommandFilterRuleViewSet'] + + +class CommandFilterViewSet(BulkModelViewSet): + permission_classes = (IsOrgAdmin,) + queryset = CommandFilter.objects.all() + serializer_class = serializers.CommandFilterSerializer + + +class CommandFilterRuleViewSet(BulkModelViewSet): + permission_classes = (IsOrgAdmin,) + serializer_class = serializers.CommandFilterRuleSerializer + + def get_queryset(self): + fpk = self.kwargs.get('filter_pk') + if not fpk: + return CommandFilterRule.objects.none() + group = get_object_or_404(CommandFilter, pk=fpk) + return group.rules.all().order_by('priority') + + diff --git a/apps/assets/api/system_user.py b/apps/assets/api/system_user.py index 6022e1b7e..16d475c35 100644 --- a/apps/assets/api/system_user.py +++ b/apps/assets/api/system_user.py @@ -33,7 +33,8 @@ __all__ = [ 'SystemUserViewSet', 'SystemUserAuthInfoApi', 'SystemUserPushApi', 'SystemUserTestConnectiveApi', 'SystemUserAssetsListView', 'SystemUserPushToAssetApi', - 'SystemUserTestAssetConnectabilityApi', + 'SystemUserTestAssetConnectabilityApi', 'SystemUserCommandFilterRuleListApi', + ] @@ -126,4 +127,17 @@ class SystemUserTestAssetConnectabilityApi(generics.RetrieveAPIView): asset_id = self.kwargs.get('aid') asset = get_object_or_404(Asset, id=asset_id) task = test_system_user_connectability_a_asset.delay(system_user, asset) - return Response({"task": task.id}) \ No newline at end of file + return Response({"task": task.id}) + + +class SystemUserCommandFilterRuleListApi(generics.ListAPIView): + permission_classes = (IsOrgAdminOrAppUser,) + + def get_serializer_class(self): + from ..serializers import CommandFilterRuleSerializer + return CommandFilterRuleSerializer + + def get_queryset(self): + pk = self.kwargs.get('pk', None) + system_user = get_object_or_404(SystemUser, pk=pk) + return system_user.cmd_filter_rules diff --git a/apps/assets/forms/__init__.py b/apps/assets/forms/__init__.py index 4eaa40948..a086cb12c 100644 --- a/apps/assets/forms/__init__.py +++ b/apps/assets/forms/__init__.py @@ -4,3 +4,4 @@ from .asset import * from .label import * from .user import * from .domain import * +from .cmd_filter import * diff --git a/apps/assets/forms/asset.py b/apps/assets/forms/asset.py index 8b132b350..28c78e981 100644 --- a/apps/assets/forms/asset.py +++ b/apps/assets/forms/asset.py @@ -48,7 +48,7 @@ class AssetCreateForm(OrgModelForm): 'root or other NOPASSWD sudo privilege user existed in asset,' 'If asset is windows or other set any one, more see admin user left menu' ), - # 'platform': _("* required Must set exact system platform, Windows, Linux ..."), + 'platform': _("Windows 2016 RDP protocol is different, If is window 2016, set it"), 'domain': _("If your have some network not connect with each other, you can set domain") } @@ -88,7 +88,7 @@ class AssetUpdateForm(OrgModelForm): 'root or other NOPASSWD sudo privilege user existed in asset,' 'If asset is windows or other set any one, more see admin user left menu' ), - # 'platform': _("* required Must set exact system platform, Windows, Linux ..."), + 'platform': _("Windows 2016 RDP protocol is different, If is window 2016, set it"), 'domain': _("If your have some network not connect with each other, you can set domain") } diff --git a/apps/assets/forms/cmd_filter.py b/apps/assets/forms/cmd_filter.py new file mode 100644 index 000000000..6cb35e631 --- /dev/null +++ b/apps/assets/forms/cmd_filter.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# +from django import forms + +from orgs.mixins import OrgModelForm +from ..models import CommandFilter, CommandFilterRule + +__all__ = ['CommandFilterForm', 'CommandFilterRuleForm'] + + +class CommandFilterForm(OrgModelForm): + class Meta: + model = CommandFilter + fields = ['name', 'comment'] + + +class CommandFilterRuleForm(OrgModelForm): + class Meta: + model = CommandFilterRule + fields = [ + 'filter', 'type', 'content', 'priority', 'action', 'comment' + ] + widgets = { + 'content': forms.Textarea(attrs={ + 'placeholder': 'eg:\r\nreboot\r\nrm -rf' + }), + } diff --git a/apps/assets/forms/user.py b/apps/assets/forms/user.py index de669bce3..740576067 100644 --- a/apps/assets/forms/user.py +++ b/apps/assets/forms/user.py @@ -3,8 +3,9 @@ from django import forms from django.utils.translation import gettext_lazy as _ -from ..models import AdminUser, SystemUser from common.utils import validate_ssh_private_key, ssh_pubkey_gen, get_logger +from orgs.mixins import OrgModelForm +from ..models import AdminUser, SystemUser logger = get_logger(__file__) __all__ = [ @@ -85,7 +86,7 @@ class AdminUserForm(PasswordAndKeyAuthForm): } -class SystemUserForm(PasswordAndKeyAuthForm): +class SystemUserForm(OrgModelForm, PasswordAndKeyAuthForm): # Admin user assets define, let user select, save it in form not in view auto_generate_key = forms.BooleanField(initial=True, required=False) @@ -136,11 +137,14 @@ class SystemUserForm(PasswordAndKeyAuthForm): fields = [ 'name', 'username', 'protocol', 'auto_generate_key', 'password', 'private_key_file', 'auto_push', 'sudo', - 'comment', 'shell', 'priority', 'login_mode', + 'comment', 'shell', 'priority', 'login_mode', 'cmd_filters', ] widgets = { 'name': forms.TextInput(attrs={'placeholder': _('Name')}), 'username': forms.TextInput(attrs={'placeholder': _('Username')}), + 'cmd_filters': forms.SelectMultiple(attrs={ + 'class': 'select2', 'data-placeholder': _('Command filter') + }), } help_texts = { 'name': '* required', diff --git a/apps/assets/models/__init__.py b/apps/assets/models/__init__.py index 35c275b99..4a3b67469 100644 --- a/apps/assets/models/__init__.py +++ b/apps/assets/models/__init__.py @@ -1,11 +1,12 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- # -from .user import AdminUser, SystemUser +from .user import * from .label import Label from .cluster import * from .group import * from .domain import * from .node import * from .asset import * +from .cmd_filter import * from .utils import * diff --git a/apps/assets/models/asset.py b/apps/assets/models/asset.py index b554c5c3a..55fb1723a 100644 --- a/apps/assets/models/asset.py +++ b/apps/assets/models/asset.py @@ -15,7 +15,7 @@ from django.core.cache import cache from ..const import ASSET_ADMIN_CONN_CACHE_KEY from .user import AdminUser, SystemUser -from orgs.mixins import OrgModelMixin,OrgManager +from orgs.mixins import OrgModelMixin, OrgManager __all__ = ['Asset'] logger = logging.getLogger(__name__) diff --git a/apps/assets/models/cmd_filter.py b/apps/assets/models/cmd_filter.py new file mode 100644 index 000000000..bd37db36e --- /dev/null +++ b/apps/assets/models/cmd_filter.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# +import uuid + +from django.db import models +from django.core.validators import MinValueValidator, MaxValueValidator +from django.utils.translation import ugettext_lazy as _ + +from orgs.mixins import OrgModelMixin + + +__all__ = [ + 'CommandFilter', 'CommandFilterRule' +] + + +class CommandFilter(OrgModelMixin): + id = models.UUIDField(default=uuid.uuid4, primary_key=True) + name = models.CharField(max_length=64, verbose_name=_("Name")) + is_active = models.BooleanField(default=True, verbose_name=_('Is active')) + comment = models.TextField(blank=True, default='', verbose_name=_("Comment")) + date_created = models.DateTimeField(auto_now_add=True) + date_updated = models.DateTimeField(auto_now=True) + created_by = models.CharField(max_length=128, blank=True, default='', verbose_name=_('Created by')) + + def __str__(self): + return self.name + + +class CommandFilterRule(OrgModelMixin): + TYPE_REGEX = 'regex' + TYPE_COMMAND = 'command' + TYPE_CHOICES = ( + (TYPE_REGEX, _('Regex')), + (TYPE_COMMAND, _('Command')), + ) + + ACTION_DENY, ACTION_ALLOW = range(2) + ACTION_CHOICES = ( + (ACTION_DENY, _('Deny')), + (ACTION_ALLOW, _('Allow')), + ) + + id = models.UUIDField(default=uuid.uuid4, primary_key=True) + filter = models.ForeignKey('CommandFilter', on_delete=models.CASCADE, verbose_name=_("Filter"), related_name='rules') + type = models.CharField(max_length=16, default=TYPE_COMMAND, choices=TYPE_CHOICES, verbose_name=_("Type")) + priority = models.IntegerField(default=50, verbose_name=_("Priority"), help_text=_("1-100, the lower will be match first"), + validators=[MinValueValidator(1), MaxValueValidator(100)]) + content = models.TextField(max_length=1024, verbose_name=_("Content"), help_text=_("One line one command")) + action = models.IntegerField(default=ACTION_DENY, choices=ACTION_CHOICES, verbose_name=_("Action")) + comment = models.CharField(max_length=64, blank=True, default='', verbose_name=_("Comment")) + date_created = models.DateTimeField(auto_now_add=True) + date_updated = models.DateTimeField(auto_now=True) + created_by = models.CharField(max_length=128, blank=True, default='', verbose_name=_('Created by')) + + class Meta: + ordering = ('priority', 'action') + + def __str__(self): + return '{} % {}'.format(self.type, self.content) diff --git a/apps/assets/models/node.py b/apps/assets/models/node.py index 25b02dc65..54535fb0a 100644 --- a/apps/assets/models/node.py +++ b/apps/assets/models/node.py @@ -40,12 +40,10 @@ class Node(OrgModelMixin): return True self_key = [int(k) for k in self.key.split(':')] other_key = [int(k) for k in other.key.split(':')] - if len(self_key) < len(other_key): - return True - elif len(self_key) > len(other_key): - return False - else: - return self_key[-1] < other_key[-1] + return self_key.__lt__(other_key) + + def __lt__(self, other): + return not self.__gt__(other) @property def name(self): diff --git a/apps/assets/models/user.py b/apps/assets/models/user.py index 646b7204f..cd90d4207 100644 --- a/apps/assets/models/user.py +++ b/apps/assets/models/user.py @@ -3,7 +3,6 @@ # import logging -import uuid from django.core.cache import cache from django.db import models @@ -118,6 +117,7 @@ class SystemUser(AssetUser): sudo = models.TextField(default='/bin/whoami', verbose_name=_('Sudo')) shell = models.CharField(max_length=64, default='/bin/bash', verbose_name=_('Shell')) login_mode = models.CharField(choices=LOGIN_MODE_CHOICES, default=AUTO_LOGIN, max_length=10, verbose_name=_('Login mode')) + cmd_filters = models.ManyToManyField('CommandFilter', related_name='system_users', verbose_name=_("Command filter"), blank=True) cache_key = "__SYSTEM_USER_CACHED_{}" @@ -163,6 +163,14 @@ class SystemUser(AssetUser): def expire_cache(self): cache.delete(self.cache_key.format(self.id)) + @property + def cmd_filter_rules(self): + from .cmd_filter import CommandFilterRule + rules = CommandFilterRule.objects.filter( + filter__in=self.cmd_filters.all() + ).order_by('priority').distinct() + return rules + @classmethod def get_system_user_by_id_or_cached(cls, sid): cached = cache.get(cls.cache_key.format(sid)) diff --git a/apps/assets/serializers/__init__.py b/apps/assets/serializers/__init__.py index 111f070a7..ad4439be3 100644 --- a/apps/assets/serializers/__init__.py +++ b/apps/assets/serializers/__init__.py @@ -7,3 +7,4 @@ from .label import * from .system_user import * from .node import * from .domain import * +from .cmd_filter import * diff --git a/apps/assets/serializers/cmd_filter.py b/apps/assets/serializers/cmd_filter.py new file mode 100644 index 000000000..e49f89bcf --- /dev/null +++ b/apps/assets/serializers/cmd_filter.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +# +from rest_framework import serializers + +from common.fields import ChoiceDisplayField +from ..models import CommandFilter, CommandFilterRule, SystemUser + + +class CommandFilterSerializer(serializers.ModelSerializer): + rules = serializers.PrimaryKeyRelatedField(queryset=CommandFilterRule.objects.all(), many=True) + system_users = serializers.PrimaryKeyRelatedField(queryset=SystemUser.objects.all(), many=True) + + class Meta: + model = CommandFilter + fields = '__all__' + + +class CommandFilterRuleSerializer(serializers.ModelSerializer): + serializer_choice_field = ChoiceDisplayField + + class Meta: + model = CommandFilterRule + fields = '__all__' diff --git a/apps/assets/templates/assets/_system_user.html b/apps/assets/templates/assets/_system_user.html index 4e1bc51a8..a8606820d 100644 --- a/apps/assets/templates/assets/_system_user.html +++ b/apps/assets/templates/assets/_system_user.html @@ -62,6 +62,10 @@ {% endblock %} +
+

{% trans 'Command filter' %}

+ {% bootstrap_field form.cmd_filters layout="horizontal" %} +

{% trans 'Other' %}

{% bootstrap_field form.sudo layout="horizontal" %} {% bootstrap_field form.shell layout="horizontal" %} @@ -101,6 +105,7 @@ var need_change_field_login_mode = [ function protocolChange() { if ($(protocol_id + " option:selected").text() === 'rdp') { $('.auth-fields').removeClass('hidden'); + $('#command-filter-block').addClass('hidden'); $.each(need_change_field, function (index, value) { $(value).closest('.form-group').addClass('hidden') }); diff --git a/apps/assets/templates/assets/admin_user_detail.html b/apps/assets/templates/assets/admin_user_detail.html index 072eb556c..f00e2352a 100644 --- a/apps/assets/templates/assets/admin_user_detail.html +++ b/apps/assets/templates/assets/admin_user_detail.html @@ -90,7 +90,7 @@ diff --git a/apps/assets/templates/assets/cmd_filter_create_update.html b/apps/assets/templates/assets/cmd_filter_create_update.html new file mode 100644 index 000000000..b1f7a57a8 --- /dev/null +++ b/apps/assets/templates/assets/cmd_filter_create_update.html @@ -0,0 +1,20 @@ +{% extends '_base_create_update.html' %} +{% load static %} +{% load bootstrap3 %} +{% load i18n %} + +{% block form %} +
+ {% csrf_token %} + {% bootstrap_field form.name layout="horizontal" %} + {% bootstrap_field form.comment layout="horizontal" %} + +
+
+
+ + +
+
+
+{% endblock %} diff --git a/apps/assets/templates/assets/cmd_filter_detail.html b/apps/assets/templates/assets/cmd_filter_detail.html new file mode 100644 index 000000000..ee68ff2f6 --- /dev/null +++ b/apps/assets/templates/assets/cmd_filter_detail.html @@ -0,0 +1,168 @@ +{% extends 'base.html' %} +{% load static %} +{% load i18n %} + +{% block custom_head_css_js %} + + +{% endblock %} + +{% block content %} +
+
+
+
+ +
+
+
+
+ {{ object.name }} +
+ + + + + + + + + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
{% trans 'Name' %}:{{ object.name }}
{% trans 'Comment' %}:{{ object.comment }}
{% trans 'Date created' %}:{{ object.date_created }}
{% trans 'Date updated' %}:{{ object.date_updated }}
{% trans 'Created by' %}:{{ object.created_by }}
+
+
+
+ +
+
+
+ {% trans 'System users' %} +
+
+ + + + + + + + + + + {% for system_user in object.system_users.all %} + + + + + {% endfor %} + +
+ +
+ +
{{ system_user }} + +
+
+
+
+
+
+
+
+
+{% endblock %} +{% block custom_foot_js %} + +{% endblock %} diff --git a/apps/assets/templates/assets/cmd_filter_list.html b/apps/assets/templates/assets/cmd_filter_list.html new file mode 100644 index 000000000..1586af8f9 --- /dev/null +++ b/apps/assets/templates/assets/cmd_filter_list.html @@ -0,0 +1,89 @@ +{% extends '_base_list.html' %} +{% load i18n static %} +{% block table_search %}{% endblock %} +{% block help_message %} +
+ {% trans 'System user bound some command filter, each command filter has some rules,'%} + {% trans 'When user login asset with this system user, then run a command,' %} + {% trans 'The command will be filter by rules, higher priority(lower number) rule run first,' %} + {% trans 'When a rule matched, if rule action is allow, then allow command execute,' %} + {% trans 'else if action is deny, then command with be deny,' %} + {% trans 'else match next rule, if none matched, allowed' %} +
+{% endblock %} +{% block table_container %} +
+ {% trans "Create command filter" %} +
+ + + + + + + + + + + + + +
+ + {% trans 'Name' %}{% trans 'Rules' %}{% trans 'System users' %}{% trans 'Comment' %}{% trans 'Action' %}
+{% endblock %} +{% block content_bottom_left %}{% endblock %} +{% block custom_foot_js %} + +{% endblock %} + + + diff --git a/apps/assets/templates/assets/cmd_filter_rule_create_update.html b/apps/assets/templates/assets/cmd_filter_rule_create_update.html new file mode 100644 index 000000000..9b240bd74 --- /dev/null +++ b/apps/assets/templates/assets/cmd_filter_rule_create_update.html @@ -0,0 +1,74 @@ +{% extends 'base.html' %} +{% load i18n %} +{% load static %} +{% load bootstrap3 %} +{% block custom_head_css_js %} + + +{% endblock %} + +{% block content %} +
+
+
+
+
+
{{ action }}
+ +
+
+
+ {% csrf_token %} + {% if form.non_field_errors %} +
+ {{ form.non_field_errors }} +
+ {% endif %} + {% bootstrap_form form layout="horizontal" %} +
+
+ + +
+
+
+
+
+
+
+
+{% endblock %} + +{% block custom_foot_js %} + +{% endblock %} \ No newline at end of file diff --git a/apps/assets/templates/assets/cmd_filter_rule_list.html b/apps/assets/templates/assets/cmd_filter_rule_list.html new file mode 100644 index 000000000..119b44fd4 --- /dev/null +++ b/apps/assets/templates/assets/cmd_filter_rule_list.html @@ -0,0 +1,115 @@ +{% extends 'base.html' %} +{% load static %} +{% load i18n %} + +{% block custom_head_css_js %} + + +{% endblock %} + +{% block content %} +
+
+
+
+ +
+
+
+
+
+
+ {% trans 'Command filter rule list' %} +
+ + + + + + + + + + +
+
+
+ + + + + + + + + + + + + + + +
+ + {% trans 'Type' %}{% trans 'Content' %}{% trans 'Priority' %}{% trans 'Strategy' %}{% trans 'Comment' %}{% trans 'Action' %}
+
+
+
+
+
+
+
+
+{% endblock %} +{% block content_bottom_left %}{% endblock %} +{% block custom_foot_js %} + +{% endblock %} diff --git a/apps/assets/templates/assets/system_user_asset.html b/apps/assets/templates/assets/system_user_asset.html index a7d5bf50b..bf778d46f 100644 --- a/apps/assets/templates/assets/system_user_asset.html +++ b/apps/assets/templates/assets/system_user_asset.html @@ -1,4 +1,5 @@ {% extends 'base.html' %} +{% load common_tags %} {% load static %} {% load i18n %} @@ -113,7 +114,7 @@ - {% for node in system_user.nodes.all %} + {% for node in system_user.nodes.all|sort %} {{ node }} diff --git a/apps/assets/templates/assets/system_user_detail.html b/apps/assets/templates/assets/system_user_detail.html index 5f16e3941..26e9bbef0 100644 --- a/apps/assets/templates/assets/system_user_detail.html +++ b/apps/assets/templates/assets/system_user_detail.html @@ -156,44 +156,47 @@ -{#
#} -{#
#} -{# {% trans 'Nodes' %}#} -{#
#} -{#
#} -{# #} -{# #} -{# #} -{# #} -{# #} -{# #} -{# #} -{# #} -{# #} -{# #} -{##} -{# {% for node in system_user.nodes.all %}#} -{# #} -{# #} -{# #} -{# #} -{# {% endfor %}#} -{# #} -{#
#} -{# #} -{#
#} -{# #} -{#
{{ node }}#} -{# #} -{#
#} -{#
#} -{#
#} + {% if system_user.protocol != 'rdp' %} +
+
+
+ {% trans 'Command filter' %} +
+
+ + + + + + + + + + + {% for cf in object.cmd_filters.all %} + + + + + {% endfor %} + +
+ +
+ +
{{ cf }} + +
+
+
+
+ {% endif %} @@ -201,27 +204,13 @@ {% endblock %} {% block custom_foot_js %} {% endblock %} diff --git a/apps/assets/urls/api_urls.py b/apps/assets/urls/api_urls.py index bdbbe5f1d..9c6865288 100644 --- a/apps/assets/urls/api_urls.py +++ b/apps/assets/urls/api_urls.py @@ -1,8 +1,11 @@ # coding:utf-8 from django.urls import path -from .. import api +from rest_framework_nested import routers +# from rest_framework.routers import DefaultRouter from rest_framework_bulk.routes import BulkRouter +from .. import api + app_name = 'assets' router = BulkRouter() @@ -13,6 +16,11 @@ router.register(r'labels', api.LabelViewSet, 'label') router.register(r'nodes', api.NodeViewSet, 'node') router.register(r'domain', api.DomainViewSet, 'domain') router.register(r'gateway', api.GatewayViewSet, 'gateway') +router.register(r'cmd-filter', api.CommandFilterViewSet, 'cmd-filter') + +cmd_filter_router = routers.NestedDefaultRouter(router, r'cmd-filter', lookup='filter') +cmd_filter_router.register(r'rules', api.CommandFilterRuleViewSet, 'cmd-filter-rule') + urlpatterns = [ path('assets-bulk/', api.AssetListUpdateApi.as_view(), name='asset-bulk-update'), @@ -42,6 +50,9 @@ urlpatterns = [ path('system-user//connective/', api.SystemUserTestConnectiveApi.as_view(), name='system-user-connective'), + path('system-user//cmd-filter-rules/', + api.SystemUserCommandFilterRuleListApi.as_view(), name='system-user-cmd-filter-rule-list'), + path('nodes//children/', api.NodeChildrenApi.as_view(), name='node-children'), path('nodes/children/', api.NodeChildrenApi.as_view(), name='node-children-2'), @@ -64,5 +75,5 @@ urlpatterns = [ api.GatewayTestConnectionApi.as_view(), name='test-gateway-connective'), ] -urlpatterns += router.urls +urlpatterns += router.urls + cmd_filter_router.urls diff --git a/apps/assets/urls/views_urls.py b/apps/assets/urls/views_urls.py index 9d160bedf..76651cfdb 100644 --- a/apps/assets/urls/views_urls.py +++ b/apps/assets/urls/views_urls.py @@ -49,4 +49,12 @@ urlpatterns = [ path('domain//gateway/create/', views.DomainGatewayCreateView.as_view(), name='domain-gateway-create'), path('domain/gateway//update/', views.DomainGatewayUpdateView.as_view(), name='domain-gateway-update'), + + path('cmd-filter/', views.CommandFilterListView.as_view(), name='cmd-filter-list'), + path('cmd-filter/create/', views.CommandFilterCreateView.as_view(), name='cmd-filter-create'), + path('cmd-filter//update/', views.CommandFilterUpdateView.as_view(), name='cmd-filter-update'), + path('cmd-filter//', views.CommandFilterDetailView.as_view(), name='cmd-filter-detail'), + path('cmd-filter//rule/', views.CommandFilterRuleListView.as_view(), name='cmd-filter-rule-list'), + path('cmd-filter//rule/create/', views.CommandFilterRuleCreateView.as_view(), name='cmd-filter-rule-create'), + path('cmd-filter//rule//update/', views.CommandFilterRuleUpdateView.as_view(), name='cmd-filter-rule-update'), ] diff --git a/apps/assets/views/__init__.py b/apps/assets/views/__init__.py index 5660d2738..04fc6c31c 100644 --- a/apps/assets/views/__init__.py +++ b/apps/assets/views/__init__.py @@ -4,3 +4,4 @@ from .system_user import * from .admin_user import * from .label import * from .domain import * +from .cmd_filter import * diff --git a/apps/assets/views/cmd_filter.py b/apps/assets/views/cmd_filter.py new file mode 100644 index 000000000..56c15885b --- /dev/null +++ b/apps/assets/views/cmd_filter.py @@ -0,0 +1,168 @@ +# -*- coding: utf-8 -*- +# + +from django.views.generic import TemplateView, CreateView, \ + UpdateView, DeleteView, DetailView +from django.views.generic.detail import SingleObjectMixin +from django.utils.translation import ugettext_lazy as _ +from django.urls import reverse_lazy +from django.shortcuts import get_object_or_404, reverse + +from common.permissions import AdminUserRequiredMixin +from common.const import create_success_msg, update_success_msg +from ..models import CommandFilter, CommandFilterRule, SystemUser +from ..forms import CommandFilterForm, CommandFilterRuleForm + + +__all__ = ( + "CommandFilterListView", "CommandFilterCreateView", + "CommandFilterUpdateView", + "CommandFilterRuleListView", "CommandFilterRuleCreateView", + "CommandFilterRuleUpdateView", "CommandFilterDetailView", +) + + +class CommandFilterListView(AdminUserRequiredMixin, TemplateView): + template_name = 'assets/cmd_filter_list.html' + + def get_context_data(self, **kwargs): + context = { + 'app': _('Assets'), + 'action': _('Command filter list'), + } + kwargs.update(context) + return super().get_context_data(**kwargs) + + +class CommandFilterCreateView(AdminUserRequiredMixin, CreateView): + model = CommandFilter + template_name = 'assets/cmd_filter_create_update.html' + form_class = CommandFilterForm + success_url = reverse_lazy('assets:cmd-filter-list') + success_message = create_success_msg + + def get_context_data(self, **kwargs): + context = { + 'app': _('Assets'), + 'action': _('Create command filter'), + } + kwargs.update(context) + return super().get_context_data(**kwargs) + + +class CommandFilterUpdateView(AdminUserRequiredMixin, UpdateView): + model = CommandFilter + template_name = 'assets/cmd_filter_create_update.html' + form_class = CommandFilterForm + success_url = reverse_lazy('assets:cmd-filter-list') + success_message = update_success_msg + + def get_context_data(self, **kwargs): + context = { + 'app': _('Assets'), + 'action': _('Update command filter'), + } + kwargs.update(context) + return super().get_context_data(**kwargs) + + +class CommandFilterDetailView(AdminUserRequiredMixin, DetailView): + model = CommandFilter + template_name = 'assets/cmd_filter_detail.html' + + def get_context_data(self, **kwargs): + system_users_remain = SystemUser.objects\ + .exclude(cmd_filters=self.object)\ + .exclude(protocol='rdp') + context = { + 'app': _('Assets'), + 'action': _('Command filter detail'), + 'system_users_remain': system_users_remain + } + kwargs.update(context) + return super().get_context_data(**kwargs) + + +class CommandFilterRuleListView(AdminUserRequiredMixin, SingleObjectMixin, TemplateView): + template_name = 'assets/cmd_filter_rule_list.html' + model = CommandFilter + object = None + + def get(self, request, *args, **kwargs): + self.object = self.get_object(queryset=self.model.objects.all()) + return super().get(request, *args, **kwargs) + + def get_context_data(self, **kwargs): + context = { + 'app': _('Assets'), + 'action': _('Command filter rule list'), + 'object': self.get_object() + } + kwargs.update(context) + return super().get_context_data(**kwargs) + + +class CommandFilterRuleCreateView(AdminUserRequiredMixin, CreateView): + template_name = 'assets/cmd_filter_rule_create_update.html' + model = CommandFilterRule + form_class = CommandFilterRuleForm + success_message = create_success_msg + cmd_filter = None + + def get_success_url(self): + return reverse('assets:cmd-filter-rule-list', kwargs={ + 'pk': self.cmd_filter.id + }) + + def get_form(self, form_class=None): + form = super().get_form(form_class=form_class) + form['filter'].initial = self.cmd_filter + form['filter'].field.widget.attrs['readonly'] = 1 + return form + + def dispatch(self, request, *args, **kwargs): + filter_pk = self.kwargs.get('filter_pk') + self.cmd_filter = get_object_or_404(CommandFilter, pk=filter_pk) + return super().dispatch(request, *args, **kwargs) + + def get_context_data(self, **kwargs): + context = { + 'app': _('Assets'), + 'action': _('Create command filter rule'), + 'object': self.cmd_filter, + } + kwargs.update(context) + return super().get_context_data(**kwargs) + + +class CommandFilterRuleUpdateView(AdminUserRequiredMixin, UpdateView): + template_name = 'assets/cmd_filter_rule_create_update.html' + model = CommandFilterRule + form_class = CommandFilterRuleForm + success_message = create_success_msg + cmd_filter = None + + def get_success_url(self): + return reverse('assets:cmd-filter-rule-list', kwargs={ + 'pk': self.cmd_filter.id + }) + + def get_form(self, form_class=None): + form = super().get_form(form_class=form_class) + form['filter'].initial = self.cmd_filter + form['filter'].field.widget.attrs['readonly'] = 1 + return form + + def dispatch(self, request, *args, **kwargs): + filter_pk = self.kwargs.get('filter_pk') + self.cmd_filter = get_object_or_404(CommandFilter, pk=filter_pk) + return super().dispatch(request, *args, **kwargs) + + def get_context_data(self, **kwargs): + context = { + 'app': _('Assets'), + 'action': _('Update command filter rule'), + 'object': self.cmd_filter, + } + kwargs.update(context) + return super().get_context_data(**kwargs) \ No newline at end of file diff --git a/apps/assets/views/system_user.py b/apps/assets/views/system_user.py index 7a8bc2bab..c31fd8da0 100644 --- a/apps/assets/views/system_user.py +++ b/apps/assets/views/system_user.py @@ -9,7 +9,7 @@ from django.views.generic.detail import DetailView from common.const import create_success_msg, update_success_msg from ..forms import SystemUserForm -from ..models import SystemUser, Node +from ..models import SystemUser, Node, CommandFilter from common.permissions import AdminUserRequiredMixin @@ -73,7 +73,7 @@ class SystemUserDetailView(AdminUserRequiredMixin, DetailView): context = { 'app': _('Assets'), 'action': _('System user detail'), - 'nodes_remain': Node.objects.exclude(systemuser=self.object) + 'cmd_filters_remain': CommandFilter.objects.exclude(system_users=self.object) } kwargs.update(context) return super().get_context_data(**kwargs) @@ -91,10 +91,11 @@ class SystemUserAssetView(AdminUserRequiredMixin, DetailView): context_object_name = 'system_user' def get_context_data(self, **kwargs): + nodes_remain = sorted(Node.objects.exclude(systemuser=self.object), reverse=True) context = { 'app': _('assets'), 'action': _('System user asset'), - 'nodes_remain': Node.objects.exclude(systemuser=self.object) + 'nodes_remain': nodes_remain } kwargs.update(context) return super().get_context_data(**kwargs) diff --git a/apps/common/fields.py b/apps/common/fields.py index 8afcdf8d9..cccc265de 100644 --- a/apps/common/fields.py +++ b/apps/common/fields.py @@ -86,3 +86,21 @@ class FormEncryptCharField(FormEncryptMixin, forms.CharField): class FormEncryptDictField(FormEncryptMixin, FormDictField): pass + + +class ChoiceDisplayField(serializers.ChoiceField): + def __init__(self, *args, **kwargs): + super(ChoiceDisplayField, self).__init__(*args, **kwargs) + self.choice_strings_to_display = { + six.text_type(key): value for key, value in self.choices.items() + } + + def to_representation(self, value): + if value is None: + return value + return { + 'value': self.choice_strings_to_values.get(six.text_type(value), + value), + 'display': self.choice_strings_to_display.get(six.text_type(value), + value), + } diff --git a/apps/common/templatetags/common_tags.py b/apps/common/templatetags/common_tags.py index 9123ecef8..7cafb0460 100644 --- a/apps/common/templatetags/common_tags.py +++ b/apps/common/templatetags/common_tags.py @@ -100,3 +100,9 @@ def is_bool_field(field): @register.filter def to_dict(data): return dict(data) + + +@register.filter +def sort(data): + print(data) + return sorted(data) diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index f7c5ab2e2..10eab3c93 100644 Binary files a/apps/locale/zh/LC_MESSAGES/django.mo and b/apps/locale/zh/LC_MESSAGES/django.mo differ diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 665798f67..9826da83e 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Jumpserver 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-12 16:54+0800\n" +"POT-Creation-Date: 2018-10-12 18:37+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: ibuler \n" "Language-Team: Jumpserver team\n" @@ -33,19 +33,19 @@ msgstr "更新节点资产硬件信息: {}" msgid "Test if the assets under the node are connectable: {}" msgstr "测试节点下资产是否可连接: {}" -#: assets/forms/asset.py:27 assets/models/asset.py:82 assets/models/user.py:113 +#: assets/forms/asset.py:27 assets/models/asset.py:82 assets/models/user.py:112 #: assets/templates/assets/asset_detail.html:183 #: assets/templates/assets/asset_detail.html:191 -#: assets/templates/assets/system_user_asset.html:94 perms/models.py:32 +#: assets/templates/assets/system_user_asset.html:95 perms/models.py:32 msgid "Nodes" 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:87 -#: assets/models/cluster.py:19 assets/models/user.py:73 +#: assets/models/cluster.py:19 assets/models/user.py:72 #: assets/templates/assets/asset_detail.html:73 templates/_nav.html:24 #: xpack/plugins/cloud/models.py:128 -#: xpack/plugins/cloud/templates/cloud/sync_task_detail.html:75 +#: xpack/plugins/cloud/templates/cloud/sync_task_detail.html:67 #: xpack/plugins/orgs/templates/orgs/org_list.html:18 msgid "Admin user" msgstr "管理用户" @@ -76,7 +76,7 @@ msgstr "网域" #: perms/templates/perms/asset_permission_list.html:57 #: perms/templates/perms/asset_permission_list.html:151 #: xpack/plugins/cloud/models.py:127 -#: xpack/plugins/cloud/templates/cloud/sync_task_detail.html:71 +#: xpack/plugins/cloud/templates/cloud/sync_task_detail.html:63 #: xpack/plugins/cloud/templates/cloud/sync_task_instance.html:66 msgid "Node" msgstr "节点" @@ -89,6 +89,10 @@ msgstr "" "root或其他拥有NOPASSWD: ALL权限的用户, 如果是windows或其它硬件可以随意设置一" "个, 更多信息查看左侧 `管理用户` 菜单" +#: assets/forms/asset.py:51 assets/forms/asset.py:91 +msgid "Windows 2016 RDP protocol is different, If is window 2016, set it" +msgstr "Windows 2016的RDP协议与之前不同,如果是请设置" + #: assets/forms/asset.py:52 assets/forms/asset.py:92 msgid "" "If your have some network not connect with each other, you can set domain" @@ -104,7 +108,7 @@ msgstr "选择资产" #: assets/models/domain.py:48 assets/templates/assets/admin_user_assets.html:53 #: assets/templates/assets/asset_detail.html:69 #: assets/templates/assets/domain_gateway_list.html:58 -#: assets/templates/assets/system_user_asset.html:51 +#: assets/templates/assets/system_user_asset.html:52 #: assets/templates/assets/user_asset_list.html:163 msgid "Port" msgstr "端口" @@ -126,7 +130,7 @@ msgstr "端口" #: terminal/templates/terminal/command_list.html:73 #: terminal/templates/terminal/session_list.html:41 #: terminal/templates/terminal/session_list.html:72 -#: xpack/plugins/cloud/models.py:173 +#: xpack/plugins/cloud/models.py:191 #: xpack/plugins/cloud/templates/cloud/sync_task_instance.html:65 #: xpack/plugins/orgs/templates/orgs/org_list.html:16 msgid "Asset" @@ -136,11 +140,14 @@ msgstr "资产" msgid "Password should not contain special characters" msgstr "不能包含特殊字符" -#: assets/forms/domain.py:59 assets/forms/user.py:79 assets/forms/user.py:142 +#: assets/forms/domain.py:59 assets/forms/user.py:80 assets/forms/user.py:143 #: assets/models/base.py:22 assets/models/cluster.py:18 -#: assets/models/domain.py:18 assets/models/group.py:20 -#: assets/models/label.py:18 assets/templates/assets/admin_user_detail.html:56 +#: assets/models/cmd_filter.py:19 assets/models/domain.py:18 +#: assets/models/group.py:20 assets/models/label.py:18 +#: assets/templates/assets/admin_user_detail.html:56 #: assets/templates/assets/admin_user_list.html:26 +#: assets/templates/assets/cmd_filter_detail.html:61 +#: assets/templates/assets/cmd_filter_list.html:24 #: assets/templates/assets/domain_detail.html:56 #: assets/templates/assets/domain_gateway_list.html:56 #: assets/templates/assets/domain_list.html:25 @@ -174,7 +181,7 @@ msgstr "不能包含特殊字符" msgid "Name" msgstr "名称" -#: assets/forms/domain.py:60 assets/forms/user.py:80 assets/forms/user.py:143 +#: assets/forms/domain.py:60 assets/forms/user.py:81 assets/forms/user.py:144 #: assets/models/base.py:23 assets/templates/assets/admin_user_detail.html:60 #: assets/templates/assets/admin_user_list.html:27 #: assets/templates/assets/domain_gateway_list.html:60 @@ -191,11 +198,11 @@ msgstr "名称" msgid "Username" msgstr "用户名" -#: assets/forms/user.py:24 +#: assets/forms/user.py:25 msgid "Password or private key passphrase" msgstr "密码或密钥密码" -#: assets/forms/user.py:25 assets/models/base.py:24 common/forms.py:104 +#: assets/forms/user.py:26 assets/models/base.py:24 common/forms.py:104 #: users/forms.py:17 users/forms.py:35 users/forms.py:47 #: users/templates/users/login.html:65 #: users/templates/users/reset_password.html:53 @@ -207,33 +214,39 @@ msgstr "密码或密钥密码" msgid "Password" msgstr "密码" -#: assets/forms/user.py:28 users/models/user.py:78 +#: assets/forms/user.py:29 users/models/user.py:78 msgid "Private key" msgstr "ssh私钥" -#: assets/forms/user.py:38 +#: assets/forms/user.py:39 msgid "Invalid private key" msgstr "ssh密钥不合法" -#: assets/forms/user.py:47 +#: assets/forms/user.py:48 msgid "Password and private key file must be input one" msgstr "密码和私钥, 必须输入一个" -#: assets/forms/user.py:128 +#: assets/forms/user.py:129 msgid "* Automatic login mode, must fill in the username." msgstr "自动登录模式,必须填写用户名" -#: assets/forms/user.py:148 +#: assets/forms/user.py:146 assets/models/user.py:120 +#: assets/templates/assets/_system_user.html:66 +#: assets/templates/assets/system_user_detail.html:165 +msgid "Command filter" +msgstr "命令过滤器" + +#: assets/forms/user.py:152 msgid "Auto push system user to asset" msgstr "自动推送系统用户到资产" -#: assets/forms/user.py:149 +#: assets/forms/user.py:153 msgid "" "High level will be using login asset as default, if user was granted more " "than 2 system user" msgstr "高优先级的系统用户将会作为默认登录用户" -#: assets/forms/user.py:151 +#: assets/forms/user.py:155 msgid "" "If you choose manual login mode, you do not need to fill in the username and " "password." @@ -245,7 +258,7 @@ msgstr "如果选择手动登录模式,用户名和密码则不需要填写" #: assets/templates/assets/asset_detail.html:61 #: assets/templates/assets/asset_list.html:93 #: assets/templates/assets/domain_gateway_list.html:57 -#: assets/templates/assets/system_user_asset.html:50 +#: assets/templates/assets/system_user_asset.html:51 #: assets/templates/assets/user_asset_list.html:46 #: assets/templates/assets/user_asset_list.html:162 #: audits/templates/audits/login_log_list.html:52 common/forms.py:133 @@ -259,7 +272,7 @@ msgstr "IP" #: assets/templates/assets/admin_user_assets.html:51 #: assets/templates/assets/asset_detail.html:57 #: assets/templates/assets/asset_list.html:92 -#: assets/templates/assets/system_user_asset.html:49 +#: assets/templates/assets/system_user_asset.html:50 #: assets/templates/assets/user_asset_list.html:45 #: assets/templates/assets/user_asset_list.html:161 common/forms.py:132 #: perms/templates/perms/asset_permission_asset.html:54 @@ -269,7 +282,7 @@ msgid "Hostname" msgstr "主机名" #: assets/models/asset.py:74 assets/models/domain.py:49 -#: assets/models/user.py:116 +#: assets/models/user.py:115 #: assets/templates/assets/domain_gateway_list.html:59 #: assets/templates/assets/system_user_detail.html:70 #: assets/templates/assets/system_user_list.html:31 @@ -283,8 +296,9 @@ msgstr "协议" msgid "Platform" msgstr "系统平台" -#: assets/models/asset.py:83 assets/models/domain.py:52 -#: assets/models/label.py:21 assets/templates/assets/asset_detail.html:105 +#: assets/models/asset.py:83 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/user_asset_list.html:169 msgid "Is active" msgstr "激活" @@ -361,9 +375,11 @@ msgid "Labels" msgstr "标签管理" #: assets/models/asset.py:126 assets/models/base.py:30 -#: assets/models/cluster.py:28 assets/models/group.py:21 +#: 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/cmd_filter_detail.html:77 #: assets/templates/assets/domain_detail.html:72 #: assets/templates/assets/system_user_detail.html:100 #: ops/templates/ops/adhoc_detail.html:86 orgs/models.py:15 perms/models.py:37 @@ -376,6 +392,7 @@ msgstr "创建者" #: assets/models/asset.py:129 assets/models/cluster.py:26 #: assets/models/domain.py:21 assets/models/group.py:22 #: assets/models/label.py:24 assets/templates/assets/admin_user_detail.html:64 +#: assets/templates/assets/cmd_filter_detail.html:69 #: assets/templates/assets/domain_detail.html:68 #: assets/templates/assets/system_user_detail.html:96 #: ops/templates/ops/adhoc_detail.html:90 ops/templates/ops/task_detail.html:63 @@ -385,18 +402,21 @@ msgstr "创建者" #: users/templates/users/user_group_detail.html:63 #: xpack/plugins/cloud/models.py:42 xpack/plugins/cloud/models.py:132 #: xpack/plugins/cloud/templates/cloud/account_detail.html:68 -#: xpack/plugins/cloud/templates/cloud/sync_task_detail.html:87 -#: xpack/plugins/cloud/templates/cloud/sync_task_list.html:19 +#: xpack/plugins/cloud/templates/cloud/sync_task_detail.html:79 #: xpack/plugins/orgs/templates/orgs/org_detail.html:60 msgid "Date created" msgstr "创建日期" #: assets/models/asset.py:131 assets/models/base.py:27 -#: assets/models/cluster.py:29 assets/models/domain.py:19 +#: assets/models/cluster.py:29 assets/models/cmd_filter.py:21 +#: assets/models/cmd_filter.py:51 assets/models/domain.py:19 #: 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/cmd_filter_detail.html:65 +#: assets/templates/assets/cmd_filter_list.html:27 +#: assets/templates/assets/cmd_filter_rule_list.html:62 #: assets/templates/assets/domain_detail.html:76 #: assets/templates/assets/domain_gateway_list.html:61 #: assets/templates/assets/domain_list.html:28 @@ -414,7 +434,7 @@ msgstr "创建日期" #: xpack/plugins/cloud/models.py:129 #: xpack/plugins/cloud/templates/cloud/account_detail.html:72 #: xpack/plugins/cloud/templates/cloud/account_list.html:15 -#: xpack/plugins/cloud/templates/cloud/sync_task_detail.html:79 +#: xpack/plugins/cloud/templates/cloud/sync_task_detail.html:71 #: xpack/plugins/cloud/templates/cloud/sync_task_list.html:20 #: xpack/plugins/orgs/templates/orgs/org_detail.html:64 #: xpack/plugins/orgs/templates/orgs/org_list.html:22 @@ -488,6 +508,82 @@ msgstr "北京电信" msgid "BGP full netcom" msgstr "BGP全网通" +#: assets/models/cmd_filter.py:34 +msgid "Regex" +msgstr "正则表达式" + +#: assets/models/cmd_filter.py:35 terminal/models.py:139 +#: terminal/templates/terminal/command_list.html:55 +#: terminal/templates/terminal/command_list.html:71 +#: terminal/templates/terminal/session_detail.html:48 +#: terminal/templates/terminal/session_list.html:77 +msgid "Command" +msgstr "命令" + +#: assets/models/cmd_filter.py:40 +msgid "Deny" +msgstr "拒绝" + +#: assets/models/cmd_filter.py:41 +msgid "Allow" +msgstr "允许" + +#: assets/models/cmd_filter.py:45 +msgid "Filter" +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 +msgid "Type" +msgstr "类型" + +#: assets/models/cmd_filter.py:47 assets/models/user.py:114 +#: assets/templates/assets/cmd_filter_rule_list.html:60 +msgid "Priority" +msgstr "优先级" + +#: assets/models/cmd_filter.py:47 +msgid "1-100, the lower will be match first" +msgstr "优先级可选范围为1-100,1最高优先级 100最低优先级" + +#: assets/models/cmd_filter.py:49 +#: assets/templates/assets/cmd_filter_rule_list.html:59 +msgid "Content" +msgstr "内容" + +#: assets/models/cmd_filter.py:49 +msgid "One line one command" +msgstr "每行一个命令" + +#: assets/models/cmd_filter.py:50 +#: assets/templates/assets/admin_user_list.html:33 +#: assets/templates/assets/asset_list.html:97 +#: assets/templates/assets/cmd_filter_list.html:28 +#: assets/templates/assets/cmd_filter_rule_list.html:63 +#: assets/templates/assets/domain_gateway_list.html:62 +#: assets/templates/assets/domain_list.html:29 +#: assets/templates/assets/label_list.html:17 +#: assets/templates/assets/system_user_asset.html:54 +#: 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 +#: 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 +#: terminal/templates/terminal/session_list.html:81 +#: terminal/templates/terminal/terminal_list.html:36 +#: users/templates/users/user_group_list.html:15 +#: users/templates/users/user_list.html:29 +#: xpack/plugins/cloud/templates/cloud/account_list.html:16 +#: xpack/plugins/cloud/templates/cloud/sync_task_list.html:21 +#: xpack/plugins/orgs/templates/orgs/org_list.html:23 +#: xpack/templates/orgs/org_list.html:15 +msgid "Action" +msgstr "动作" + #: assets/models/domain.py:59 assets/templates/assets/domain_detail.html:21 #: assets/templates/assets/domain_detail.html:64 #: assets/templates/assets/domain_gateway_list.html:21 @@ -542,57 +638,56 @@ msgstr "分类" msgid "Key" msgstr "" -#: assets/models/user.py:109 +#: assets/models/user.py:108 msgid "Automatic login" msgstr "自动登录" -#: assets/models/user.py:110 +#: assets/models/user.py:109 msgid "Manually login" msgstr "手动登录" -#: assets/models/user.py:114 +#: assets/models/user.py:113 #: assets/templates/assets/_asset_group_bulk_update_modal.html:11 -#: assets/templates/assets/system_user_asset.html:21 +#: assets/templates/assets/system_user_asset.html:22 #: assets/templates/assets/system_user_detail.html:22 #: assets/views/admin_user.py:29 assets/views/admin_user.py:47 #: assets/views/admin_user.py:63 assets/views/admin_user.py:78 #: assets/views/admin_user.py:102 assets/views/asset.py:53 #: assets/views/asset.py:92 assets/views/asset.py:136 assets/views/asset.py:153 -#: assets/views/asset.py:177 assets/views/domain.py:29 -#: assets/views/domain.py:45 assets/views/domain.py:61 -#: assets/views/domain.py:74 assets/views/domain.py:98 -#: assets/views/domain.py:126 assets/views/domain.py:145 -#: assets/views/label.py:26 assets/views/label.py:42 assets/views/label.py:58 -#: assets/views/system_user.py:28 assets/views/system_user.py:44 -#: assets/views/system_user.py:60 assets/views/system_user.py:74 -#: templates/_nav.html:19 +#: assets/views/asset.py:177 assets/views/cmd_filter.py:30 +#: assets/views/cmd_filter.py:46 assets/views/cmd_filter.py:62 +#: assets/views/cmd_filter.py:78 assets/views/cmd_filter.py:97 +#: assets/views/cmd_filter.py:130 assets/views/cmd_filter.py:163 +#: assets/views/domain.py:29 assets/views/domain.py:45 +#: assets/views/domain.py:61 assets/views/domain.py:74 +#: assets/views/domain.py:98 assets/views/domain.py:126 +#: assets/views/domain.py:145 assets/views/label.py:26 assets/views/label.py:42 +#: assets/views/label.py:58 assets/views/system_user.py:28 +#: assets/views/system_user.py:44 assets/views/system_user.py:60 +#: assets/views/system_user.py:74 templates/_nav.html:19 msgid "Assets" msgstr "资产管理" -#: assets/models/user.py:115 -msgid "Priority" -msgstr "优先级" - -#: assets/models/user.py:117 assets/templates/assets/_system_user.html:59 +#: assets/models/user.py:116 assets/templates/assets/_system_user.html:59 #: assets/templates/assets/system_user_detail.html:122 #: assets/templates/assets/system_user_update.html:10 msgid "Auto push" msgstr "自动推送" -#: assets/models/user.py:118 assets/templates/assets/system_user_detail.html:74 +#: assets/models/user.py:117 assets/templates/assets/system_user_detail.html:74 msgid "Sudo" msgstr "Sudo" -#: assets/models/user.py:119 assets/templates/assets/system_user_detail.html:79 +#: assets/models/user.py:118 assets/templates/assets/system_user_detail.html:79 msgid "Shell" msgstr "Shell" -#: assets/models/user.py:120 assets/templates/assets/system_user_detail.html:66 +#: assets/models/user.py:119 assets/templates/assets/system_user_detail.html:66 #: assets/templates/assets/system_user_list.html:32 msgid "Login mode" msgstr "登录模式" -#: assets/models/user.py:181 assets/templates/assets/user_asset_list.html:167 +#: assets/models/user.py:189 assets/templates/assets/user_asset_list.html:167 #: audits/models.py:19 audits/templates/audits/ftp_log_list.html:49 #: audits/templates/audits/ftp_log_list.html:72 perms/forms.py:40 #: perms/models.py:33 perms/models.py:81 @@ -670,6 +765,8 @@ msgid "Select Asset" msgstr "选择资产" #: assets/templates/assets/_asset_group_bulk_update_modal.html:21 +#: assets/templates/assets/cmd_filter_detail.html:89 +#: assets/templates/assets/cmd_filter_list.html:26 #: assets/templates/assets/user_asset_list.html:48 #: users/templates/users/user_granted_asset.html:47 msgid "System users" @@ -730,7 +827,7 @@ msgstr "认证" msgid "Auto generate key" msgstr "自动生成密钥" -#: assets/templates/assets/_system_user.html:65 +#: assets/templates/assets/_system_user.html:69 #: assets/templates/assets/asset_create.html:60 #: assets/templates/assets/asset_update.html:64 #: assets/templates/assets/gateway_create_update.html:53 @@ -739,11 +836,13 @@ msgstr "自动生成密钥" msgid "Other" msgstr "其它" -#: assets/templates/assets/_system_user.html:71 +#: assets/templates/assets/_system_user.html:75 #: assets/templates/assets/admin_user_create_update.html:45 #: assets/templates/assets/asset_bulk_update.html:23 #: assets/templates/assets/asset_create.html:67 #: assets/templates/assets/asset_update.html:71 +#: assets/templates/assets/cmd_filter_create_update.html:15 +#: assets/templates/assets/cmd_filter_rule_create_update.html:40 #: assets/templates/assets/domain_create_update.html:16 #: assets/templates/assets/gateway_create_update.html:58 #: assets/templates/assets/label_create_update.html:18 @@ -767,12 +866,14 @@ msgstr "其它" msgid "Reset" msgstr "重置" -#: assets/templates/assets/_system_user.html:72 +#: assets/templates/assets/_system_user.html:76 #: assets/templates/assets/admin_user_create_update.html:46 #: assets/templates/assets/asset_bulk_update.html:24 #: assets/templates/assets/asset_create.html:68 #: assets/templates/assets/asset_list.html:114 #: assets/templates/assets/asset_update.html:72 +#: assets/templates/assets/cmd_filter_create_update.html:16 +#: assets/templates/assets/cmd_filter_rule_create_update.html:41 #: assets/templates/assets/domain_create_update.html:17 #: assets/templates/assets/gateway_create_update.html:59 #: assets/templates/assets/label_create_update.html:19 @@ -807,9 +908,11 @@ msgstr "关闭" #: assets/templates/assets/admin_user_assets.html:18 #: assets/templates/assets/admin_user_detail.html:18 +#: assets/templates/assets/cmd_filter_detail.html:19 +#: assets/templates/assets/cmd_filter_rule_list.html:19 #: assets/templates/assets/domain_detail.html:18 #: assets/templates/assets/domain_gateway_list.html:18 -#: assets/templates/assets/system_user_asset.html:17 +#: assets/templates/assets/system_user_asset.html:18 #: assets/templates/assets/system_user_detail.html:18 #: ops/templates/ops/adhoc_history.html:130 #: ops/templates/ops/task_adhoc.html:116 @@ -832,14 +935,14 @@ msgstr "资产列表" #: assets/templates/assets/admin_user_assets.html:54 #: assets/templates/assets/admin_user_list.html:29 -#: assets/templates/assets/system_user_asset.html:52 +#: assets/templates/assets/system_user_asset.html:53 #: assets/templates/assets/system_user_list.html:34 #: users/templates/users/user_group_granted_asset.html:47 msgid "Reachable" msgstr "可连接" #: assets/templates/assets/admin_user_assets.html:66 -#: assets/templates/assets/system_user_asset.html:65 +#: assets/templates/assets/system_user_asset.html:66 #: assets/templates/assets/system_user_detail.html:116 #: perms/templates/perms/asset_permission_detail.html:114 msgid "Quick update" @@ -852,8 +955,8 @@ msgstr "测试可连接性" #: assets/templates/assets/admin_user_assets.html:75 #: assets/templates/assets/asset_detail.html:171 -#: assets/templates/assets/system_user_asset.html:74 -#: assets/templates/assets/system_user_asset.html:160 +#: assets/templates/assets/system_user_asset.html:75 +#: assets/templates/assets/system_user_asset.html:161 #: assets/templates/assets/system_user_detail.html:151 msgid "Test" msgstr "测试" @@ -862,6 +965,9 @@ msgstr "测试" #: assets/templates/assets/admin_user_list.html:88 #: assets/templates/assets/asset_detail.html:24 #: assets/templates/assets/asset_list.html:171 +#: assets/templates/assets/cmd_filter_detail.html:29 +#: assets/templates/assets/cmd_filter_list.html:57 +#: assets/templates/assets/cmd_filter_rule_list.html:86 #: assets/templates/assets/domain_detail.html:24 #: assets/templates/assets/domain_detail.html:103 #: assets/templates/assets/domain_gateway_list.html:85 @@ -892,6 +998,9 @@ msgstr "更新" #: assets/templates/assets/admin_user_list.html:89 #: assets/templates/assets/asset_detail.html:28 #: assets/templates/assets/asset_list.html:172 +#: assets/templates/assets/cmd_filter_detail.html:33 +#: assets/templates/assets/cmd_filter_list.html:58 +#: assets/templates/assets/cmd_filter_rule_list.html:87 #: assets/templates/assets/domain_detail.html:28 #: assets/templates/assets/domain_detail.html:104 #: assets/templates/assets/domain_gateway_list.html:86 @@ -911,7 +1020,7 @@ msgstr "更新" #: xpack/plugins/cloud/templates/cloud/account_detail.html:29 #: xpack/plugins/cloud/templates/cloud/account_list.html:40 #: xpack/plugins/cloud/templates/cloud/sync_task_detail.html:32 -#: xpack/plugins/cloud/templates/cloud/sync_task_list.html:45 +#: xpack/plugins/cloud/templates/cloud/sync_task_list.html:49 #: xpack/plugins/orgs/templates/orgs/org_detail.html:29 #: xpack/plugins/orgs/templates/orgs/org_list.html:87 #: xpack/templates/orgs/org_list.html:45 @@ -930,8 +1039,9 @@ msgstr "选择节点" #: assets/templates/assets/admin_user_detail.html:100 #: assets/templates/assets/asset_detail.html:200 #: assets/templates/assets/asset_list.html:633 -#: assets/templates/assets/system_user_asset.html:111 -#: assets/templates/assets/system_user_detail.html:330 +#: 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 #: terminal/templates/terminal/session_detail.html:108 #: users/templates/users/user_detail.html:382 @@ -983,29 +1093,6 @@ msgstr "不可达" msgid "Ratio" msgstr "比例" -#: assets/templates/assets/admin_user_list.html:33 -#: assets/templates/assets/asset_list.html:97 -#: assets/templates/assets/domain_gateway_list.html:62 -#: assets/templates/assets/domain_list.html:29 -#: assets/templates/assets/label_list.html:17 -#: assets/templates/assets/system_user_asset.html:53 -#: 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 -#: 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 -#: terminal/templates/terminal/session_list.html:81 -#: terminal/templates/terminal/terminal_list.html:36 -#: users/templates/users/user_group_list.html:15 -#: users/templates/users/user_list.html:29 -#: xpack/plugins/cloud/templates/cloud/account_list.html:16 -#: xpack/plugins/cloud/templates/cloud/sync_task_list.html:21 -#: xpack/plugins/orgs/templates/orgs/org_list.html:23 -#: xpack/templates/orgs/org_list.html:15 -msgid "Action" -msgstr "动作" - #: assets/templates/assets/asset_bulk_update.html:8 #: users/templates/users/user_bulk_update.html:8 msgid "Select properties that need to be modified" @@ -1191,7 +1278,6 @@ msgid "This will delete the selected assets !!!" msgstr "删除选择资产" #: assets/templates/assets/asset_list.html:631 -#: assets/templates/assets/system_user_detail.html:328 #: assets/templates/assets/system_user_list.html:141 #: users/templates/users/user_detail.html:380 #: users/templates/users/user_detail.html:406 @@ -1220,6 +1306,66 @@ msgstr "删除失败" msgid "Configuration" msgstr "配置" +#: assets/templates/assets/cmd_filter_detail.html:25 +#: assets/templates/assets/cmd_filter_list.html:25 +#: assets/templates/assets/cmd_filter_rule_list.html:23 +msgid "Rules" +msgstr "规则" + +#: assets/templates/assets/cmd_filter_detail.html:73 +msgid "Date updated" +msgstr "更新日期" + +#: assets/templates/assets/cmd_filter_detail.html:97 +msgid "Binding to system user" +msgstr "绑定到系统用户" + +#: assets/templates/assets/cmd_filter_list.html:6 +msgid "" +"System user bound some command filter, each command filter has some rules," +msgstr "系统用户可以绑定一些命令过滤器,一个过滤器可以定义一些规则" + +#: assets/templates/assets/cmd_filter_list.html:7 +msgid "When user login asset with this system user, then run a command," +msgstr "当用户使用这个系统用户登录资产,然后执行一个命令" + +#: assets/templates/assets/cmd_filter_list.html:8 +msgid "" +"The command will be filter by rules, higher priority(lower number) rule run " +"first," +msgstr "这个命令需要被绑定过滤器的所有规则匹配,高优先级(数字越低)先被匹配," + +#: assets/templates/assets/cmd_filter_list.html:9 +msgid "" +"When a rule matched, if rule action is allow, then allow command execute," +msgstr "当一个规则匹配到了,如果规则的动作是 允许, 这个命令会被放行," + +#: assets/templates/assets/cmd_filter_list.html:10 +msgid "else if action is deny, then command with be deny," +msgstr "如果规则的动作是 禁止,命令将会被禁止执行," + +#: assets/templates/assets/cmd_filter_list.html:11 +msgid "else match next rule, if none matched, allowed" +msgstr "否则就匹配下一个规则,如果最后没有匹配到规则,则允许执行" + +#: assets/templates/assets/cmd_filter_list.html:16 +#: assets/views/cmd_filter.py:47 +msgid "Create command filter" +msgstr "创建命令过滤器" + +#: assets/templates/assets/cmd_filter_rule_list.html:33 +#: assets/views/cmd_filter.py:98 +msgid "Command filter rule list" +msgstr "命令过滤器列表" + +#: assets/templates/assets/cmd_filter_rule_list.html:50 +msgid "Create rule" +msgstr "创建规则" + +#: assets/templates/assets/cmd_filter_rule_list.html:61 +msgid "Strategy" +msgstr "策略" + #: assets/templates/assets/delete_confirm.html:6 #: perms/templates/perms/delete_confirm.html:6 templates/delete_confirm.html:6 msgid "Confirm delete" @@ -1275,27 +1421,27 @@ msgstr "创建网域" msgid "Create label" msgstr "创建标签" -#: assets/templates/assets/system_user_asset.html:30 +#: assets/templates/assets/system_user_asset.html:31 msgid "Assets of " msgstr "资产" -#: assets/templates/assets/system_user_asset.html:71 +#: assets/templates/assets/system_user_asset.html:72 #: assets/templates/assets/system_user_detail.html:148 msgid "Test assets connective" msgstr "测试资产可连接性" -#: assets/templates/assets/system_user_asset.html:80 +#: assets/templates/assets/system_user_asset.html:81 #: assets/templates/assets/system_user_detail.html:139 msgid "Push system user now" msgstr "立刻推送系统" -#: assets/templates/assets/system_user_asset.html:83 -#: assets/templates/assets/system_user_asset.html:158 +#: assets/templates/assets/system_user_asset.html:84 +#: assets/templates/assets/system_user_asset.html:159 #: assets/templates/assets/system_user_detail.html:142 msgid "Push" msgstr "推送" -#: assets/templates/assets/system_user_asset.html:102 +#: assets/templates/assets/system_user_asset.html:103 msgid "Add to node" msgstr "添加到节点" @@ -1307,17 +1453,9 @@ msgstr "家目录" msgid "Uid" msgstr "Uid" -#: assets/templates/assets/system_user_detail.html:324 -msgid "Are you sure to remove authentication information for the system user ?" -msgstr "你确定清除该系统用户的认证信息吗 ?" - -#: assets/templates/assets/system_user_detail.html:336 -msgid "Clear auth" -msgstr "清除认证信息" - -#: assets/templates/assets/system_user_detail.html:336 -msgid "success" -msgstr "成功" +#: assets/templates/assets/system_user_detail.html:173 +msgid "Binding command filters" +msgstr "绑定命令过滤器" #: assets/templates/assets/system_user_list.html:10 msgid "" @@ -1403,6 +1541,26 @@ msgstr "更新资产" msgid "already exists" msgstr "已经存在" +#: assets/views/cmd_filter.py:31 +msgid "Command filter list" +msgstr "命令过滤器列表" + +#: assets/views/cmd_filter.py:63 +msgid "Update command filter" +msgstr "更新命令过滤器" + +#: assets/views/cmd_filter.py:79 +msgid "Command filter detail" +msgstr "命令过滤器详情" + +#: assets/views/cmd_filter.py:131 +msgid "Create command filter rule" +msgstr "创建命令过滤器规则" + +#: assets/views/cmd_filter.py:164 +msgid "Update command filter rule" +msgstr "更新命令过滤器规则" + #: assets/views/domain.py:30 templates/_nav.html:23 msgid "Domain list" msgstr "网域列表" @@ -1443,11 +1601,11 @@ msgstr "更新系统用户" msgid "System user detail" msgstr "系统用户详情" -#: assets/views/system_user.py:95 +#: assets/views/system_user.py:96 msgid "assets" msgstr "资产管理" -#: assets/views/system_user.py:96 +#: assets/views/system_user.py:97 msgid "System user asset" msgstr "系统用户集群资产" @@ -1471,8 +1629,8 @@ msgstr "文件名" #: audits/models.py:22 audits/templates/audits/ftp_log_list.html:76 #: ops/templates/ops/task_list.html:39 users/models/authentication.py:66 -#: users/templates/users/user_detail.html:452 xpack/plugins/cloud/api.py:55 -#: xpack/plugins/cloud/api.py:84 +#: users/templates/users/user_detail.html:452 xpack/plugins/cloud/api.py:60 +#: xpack/plugins/cloud/api.py:89 msgid "Success" msgstr "成功" @@ -1530,12 +1688,6 @@ msgstr "搜索" msgid "ID" msgstr "ID" -#: audits/templates/audits/login_log_list.html:50 -#: common/templates/common/terminal_setting.html:73 -#: common/templates/common/terminal_setting.html:91 -msgid "Type" -msgstr "类型" - #: audits/templates/audits/login_log_list.html:51 msgid "UA" msgstr "Agent" @@ -1551,14 +1703,14 @@ msgid "MFA" msgstr "MFA" #: audits/templates/audits/login_log_list.html:55 -#: users/models/authentication.py:76 xpack/plugins/cloud/models.py:158 +#: users/models/authentication.py:76 xpack/plugins/cloud/models.py:176 #: xpack/plugins/cloud/templates/cloud/sync_task_history.html:67 msgid "Reason" msgstr "原因" #: audits/templates/audits/login_log_list.html:56 -#: users/models/authentication.py:77 xpack/plugins/cloud/models.py:157 -#: xpack/plugins/cloud/models.py:174 +#: users/models/authentication.py:77 xpack/plugins/cloud/models.py:175 +#: xpack/plugins/cloud/models.py:192 #: xpack/plugins/cloud/templates/cloud/sync_task_history.html:68 #: xpack/plugins/cloud/templates/cloud/sync_task_instance.html:67 msgid "Status" @@ -1578,19 +1730,19 @@ msgid "Datetime" msgstr "日期" #: audits/views.py:66 audits/views.py:110 audits/views.py:143 -#: templates/_nav.html:67 +#: templates/_nav.html:73 msgid "Audits" msgstr "日志审计" -#: audits/views.py:67 templates/_nav.html:71 +#: audits/views.py:67 templates/_nav.html:77 msgid "FTP log" msgstr "FTP日志" -#: audits/views.py:111 templates/_nav.html:72 +#: audits/views.py:111 templates/_nav.html:78 msgid "Operate log" msgstr "操作日志" -#: audits/views.py:144 templates/_nav.html:73 +#: audits/views.py:144 templates/_nav.html:79 msgid "Password change log" msgstr "改密日志" @@ -1602,7 +1754,7 @@ msgstr "改密日志" msgid "Users" msgstr "用户管理" -#: audits/views.py:184 templates/_nav.html:70 +#: audits/views.py:184 templates/_nav.html:76 msgid "Login log" msgstr "登录日志" @@ -1924,7 +2076,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:104 +#: common/views.py:129 templates/_nav.html:108 msgid "Settings" msgstr "系统设置" @@ -1970,7 +2122,7 @@ msgstr "任务" #: ops/models/adhoc.py:157 ops/templates/ops/adhoc_detail.html:57 #: ops/templates/ops/task_adhoc.html:60 msgid "Pattern" -msgstr "" +msgstr "模式" #: ops/models/adhoc.py:158 ops/templates/ops/adhoc_detail.html:61 msgid "Options" @@ -2168,7 +2320,7 @@ msgid "Versions" msgstr "版本" #: ops/templates/ops/task_list.html:71 -#: xpack/plugins/cloud/templates/cloud/sync_task_list.html:43 +#: xpack/plugins/cloud/templates/cloud/sync_task_list.html:47 msgid "Run" msgstr "执行" @@ -2181,7 +2333,7 @@ msgstr "任务开始: " msgid "Ops" msgstr "作业中心" -#: ops/views.py:37 templates/_nav.html:61 +#: ops/views.py:37 templates/_nav.html:67 msgid "Task list" msgstr "任务列表" @@ -2219,7 +2371,7 @@ msgstr "资产和节点至少选一个" msgid "Date expired" msgstr "失效日期" -#: perms/models.py:45 perms/models.py:92 templates/_nav.html:33 +#: perms/models.py:45 perms/models.py:92 templates/_nav.html:34 msgid "Asset permission" msgstr "资产授权" @@ -2307,7 +2459,7 @@ msgid "Select user groups" msgstr "选择用户组" #: perms/views.py:23 perms/views.py:53 perms/views.py:68 perms/views.py:83 -#: perms/views.py:118 perms/views.py:150 templates/_nav.html:30 +#: perms/views.py:118 perms/views.py:150 templates/_nav.html:31 #: xpack/plugins/orgs/templates/orgs/org_list.html:21 msgid "Perms" msgstr "权限管理" @@ -2410,46 +2562,54 @@ msgstr "" msgid "User list" msgstr "用户列表" -#: templates/_nav.html:39 +#: templates/_nav.html:27 +msgid "Command filters" +msgstr "命令过滤" + +#: templates/_nav.html:40 msgid "Sessions" msgstr "会话管理" -#: templates/_nav.html:42 +#: templates/_nav.html:43 msgid "Session online" msgstr "在线会话" -#: templates/_nav.html:43 +#: templates/_nav.html:44 msgid "Session offline" msgstr "历史会话" -#: templates/_nav.html:44 +#: templates/_nav.html:45 msgid "Commands" msgstr "命令记录" -#: templates/_nav.html:47 templates/_nav_user.html:14 +#: templates/_nav.html:48 templates/_nav_user.html:14 msgid "Web terminal" msgstr "Web终端" -#: templates/_nav.html:51 terminal/views/command.py:50 +#: templates/_nav.html:53 +msgid "File manager" +msgstr "文件管理" + +#: templates/_nav.html:57 terminal/views/command.py:50 #: terminal/views/session.py:75 terminal/views/session.py:93 #: terminal/views/session.py:115 terminal/views/terminal.py:31 #: terminal/views/terminal.py:46 terminal/views/terminal.py:58 msgid "Terminal" msgstr "终端管理" -#: templates/_nav.html:58 +#: templates/_nav.html:64 msgid "Job Center" msgstr "作业中心" -#: templates/_nav.html:88 +#: templates/_nav.html:94 msgid "XPack" msgstr "" -#: templates/_nav.html:95 xpack/plugins/cloud/views.py:26 +#: templates/_nav.html:100 xpack/plugins/cloud/views.py:26 msgid "Account list" msgstr "账户列表" -#: templates/_nav.html:96 xpack/plugins/cloud/views.py:85 +#: templates/_nav.html:101 xpack/plugins/cloud/views.py:85 msgid "Sync task list" msgstr "同步任务列表" @@ -2691,13 +2851,6 @@ msgstr "运行时间" msgid "Replay" msgstr "回放" -#: terminal/models.py:139 terminal/templates/terminal/command_list.html:55 -#: terminal/templates/terminal/command_list.html:71 -#: terminal/templates/terminal/session_detail.html:48 -#: terminal/templates/terminal/session_list.html:77 -msgid "Command" -msgstr "命令" - #: terminal/models.py:142 msgid "Date last active" msgstr "最后活跃日期" @@ -2779,10 +2932,8 @@ msgid "Terminate task send, waiting ..." msgstr "终断任务已发送,请等待" #: terminal/templates/terminal/session_list.html:156 -#, fuzzy -#| msgid "MFA enable success" msgid "Finish session success" -msgstr "MFA 绑定成功" +msgstr "标记会话完成成功" #: terminal/templates/terminal/terminal_detail.html:13 #: terminal/views/terminal.py:59 @@ -2837,15 +2988,15 @@ msgstr "终端列表" msgid "Update terminal" msgstr "更新终端" -#: terminal/views/terminal.py:102 terminal/views/terminal.py:103 +#: terminal/views/terminal.py:105 terminal/views/terminal.py:106 msgid "Redirect to web terminal" msgstr "重定向到web terminal" -#: terminal/views/terminal.py:110 +#: terminal/views/terminal.py:113 msgid "Connect ssh terminal" msgstr "连接ssh终端" -#: terminal/views/terminal.py:111 +#: terminal/views/terminal.py:114 msgid "" "You should use your ssh client tools connect terminal: {}

{}" msgstr "你可以使用ssh客户端工具连接终端" @@ -3047,8 +3198,8 @@ msgstr "用户名/密码 校验失败" msgid "MFA authentication failed" msgstr "MFA 认证失败" -#: users/models/authentication.py:67 xpack/plugins/cloud/models.py:150 -#: xpack/plugins/cloud/models.py:164 +#: users/models/authentication.py:67 xpack/plugins/cloud/models.py:168 +#: xpack/plugins/cloud/models.py:182 msgid "Failed" msgstr "失败" @@ -3891,19 +4042,15 @@ msgstr "MFA 解绑成功" msgid "MFA disable success, return login page" msgstr "MFA 解绑成功,返回登录页面" -#: xpack/plugins/cloud/api.py:54 xpack/plugins/cloud/providers/provider.py:76 -#, fuzzy -#| msgid "Unavailable" +#: xpack/plugins/cloud/api.py:59 xpack/plugins/cloud/providers/provider.py:75 msgid "Account unavailable" -msgstr "无效" +msgstr "账户无效" -#: xpack/plugins/cloud/api.py:79 -#, fuzzy -#| msgid "Create sync task" +#: xpack/plugins/cloud/api.py:84 msgid "Get sync task error" -msgstr "创建同步任务" +msgstr "获取同步任务" -#: xpack/plugins/cloud/api.py:82 +#: xpack/plugins/cloud/api.py:87 msgid "New provider error" msgstr "" @@ -3992,37 +4139,38 @@ msgid "Instances" msgstr "实例" #: xpack/plugins/cloud/models.py:130 -#: xpack/plugins/cloud/templates/cloud/sync_task_detail.html:83 +#: xpack/plugins/cloud/templates/cloud/sync_task_detail.html:75 +#: xpack/plugins/cloud/templates/cloud/sync_task_list.html:19 msgid "Date last sync" msgstr "最后同步日期" -#: xpack/plugins/cloud/models.py:151 xpack/plugins/cloud/models.py:165 +#: xpack/plugins/cloud/models.py:169 xpack/plugins/cloud/models.py:183 msgid "Succeed" msgstr "成功" -#: xpack/plugins/cloud/models.py:152 +#: xpack/plugins/cloud/models.py:170 msgid "Partial succeed" msgstr "" -#: xpack/plugins/cloud/models.py:155 xpack/plugins/cloud/models.py:169 +#: xpack/plugins/cloud/models.py:173 xpack/plugins/cloud/models.py:187 msgid "Sync task" msgstr "同步任务" -#: xpack/plugins/cloud/models.py:156 +#: xpack/plugins/cloud/models.py:174 msgid "Result" msgstr "" -#: xpack/plugins/cloud/models.py:159 xpack/plugins/cloud/models.py:175 +#: xpack/plugins/cloud/models.py:177 xpack/plugins/cloud/models.py:193 #: xpack/plugins/cloud/templates/cloud/sync_task_history.html:69 #: xpack/plugins/cloud/templates/cloud/sync_task_instance.html:68 msgid "Date sync" msgstr "同步日期" -#: xpack/plugins/cloud/models.py:166 +#: xpack/plugins/cloud/models.py:184 msgid "Exist" msgstr "存在" -#: xpack/plugins/cloud/models.py:170 +#: xpack/plugins/cloud/models.py:188 #: xpack/plugins/cloud/templates/cloud/sync_task_detail.html:25 #: xpack/plugins/cloud/templates/cloud/sync_task_history.html:26 #: xpack/plugins/cloud/templates/cloud/sync_task_instance.html:26 @@ -4030,14 +4178,14 @@ msgstr "存在" msgid "Sync task history" msgstr "同步历史列表" -#: xpack/plugins/cloud/models.py:171 -#: xpack/plugins/cloud/templates/cloud/sync_task_detail.html:67 +#: xpack/plugins/cloud/models.py:189 +#: xpack/plugins/cloud/templates/cloud/sync_task_detail.html:91 #: xpack/plugins/cloud/templates/cloud/sync_task_instance.html:63 msgid "Instance" msgstr "实例" -#: xpack/plugins/cloud/models.py:172 -#: xpack/plugins/cloud/templates/cloud/sync_task_detail.html:63 +#: xpack/plugins/cloud/models.py:190 +#: xpack/plugins/cloud/templates/cloud/sync_task_detail.html:83 #: xpack/plugins/cloud/templates/cloud/sync_task_instance.html:64 msgid "Region" msgstr "地域" @@ -4057,10 +4205,8 @@ msgid "Loading..." msgstr "" #: xpack/plugins/cloud/templates/cloud/sync_task_create.html:106 -#, fuzzy -#| msgid "Create node failed" msgid "Load failed" -msgstr "创建节点失败" +msgstr "加载失败" #: xpack/plugins/cloud/templates/cloud/sync_task_detail.html:22 #: xpack/plugins/cloud/templates/cloud/sync_task_history.html:23 @@ -4097,7 +4243,7 @@ msgstr "存在" msgid "Create sync task" msgstr "创建同步任务" -#: xpack/plugins/cloud/templates/cloud/sync_task_list.html:80 +#: xpack/plugins/cloud/templates/cloud/sync_task_list.html:84 msgid "Sync success" msgstr "同步成功" @@ -4149,6 +4295,16 @@ msgstr "创建组织" msgid "Update org" msgstr "更新组织" +#~ msgid "" +#~ "Are you sure to remove authentication information for the system user ?" +#~ msgstr "你确定清除该系统用户的认证信息吗 ?" + +#~ msgid "Clear auth" +#~ msgstr "清除认证信息" + +#~ msgid "success" +#~ msgstr "成功" + #~ msgid "Task has been send, Go to ops task list seen result" #~ msgstr "任务已下发,查看ops任务列表" diff --git a/apps/orgs/views.py b/apps/orgs/views.py index 374f34812..5a363df0a 100644 --- a/apps/orgs/views.py +++ b/apps/orgs/views.py @@ -14,7 +14,8 @@ class SwitchOrgView(DetailView): pk = kwargs.get('pk') self.object = Organization.get_instance(pk) request.session['oid'] = self.object.id.__str__() - return redirect('index') + referer = request.META.get('HTTP_REFERER', reverse('index')) + return redirect(referer) class SwitchToAOrgView(View): diff --git a/apps/static/plugins/elfinder/css/theme-gray.css b/apps/static/plugins/elfinder/css/theme-gray.css index 6b136a64d..5c2b35d9e 100644 --- a/apps/static/plugins/elfinder/css/theme-gray.css +++ b/apps/static/plugins/elfinder/css/theme-gray.css @@ -1528,9 +1528,15 @@ a.ui-button:active .ui-icon, .std42-dialog .ui-dialog-titlebar .elfinder-titlebar-minimize:hover .ui-icon { background-color: #ff9800; } -.elfinder-dialog-title { +.elfinder-dialog-title { color: #f1f1f1; + } + +.ui-dialog-buttonpane { + background: #fff; +} + .std42-dialog .ui-dialog-content { background: #fff; } diff --git a/apps/static/plugins/elfinder/i18n/elfinder.zh_CN.js b/apps/static/plugins/elfinder/i18n/elfinder.zh_CN.js index cbbfc12bc..a80e7c4b5 100755 --- a/apps/static/plugins/elfinder/i18n/elfinder.zh_CN.js +++ b/apps/static/plugins/elfinder/i18n/elfinder.zh_CN.js @@ -375,7 +375,7 @@ 'pass' : '密码', // added 18.04.2012 'confirmUnmount' : '确实要卸载 $1?', // from v2.1 added 30.04.2012 'dropFilesBrowser': '从浏览器中拖放或粘贴文件', // from v2.1 added 30.05.2012 - 'dropPasteFiles' : '拖放文件,粘贴网址或剪贴板图像', // from v2.1 added 07.04.2014 + 'dropPasteFiles' : '拖放文件,或粘贴剪贴板图像', // from v2.1 added 07.04.2014 'encoding' : '编码', // from v2.1 added 19.12.2014 'locale' : '语言环境', // from v2.1 added 19.12.2014 'searchTarget' : '目标: $1', // from v2.1 added 22.5.2015 diff --git a/apps/templates/_footer.html b/apps/templates/_footer.html index 088276a0d..12c285f92 100644 --- a/apps/templates/_footer.html +++ b/apps/templates/_footer.html @@ -1,7 +1,7 @@ {% load i18n %}