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 @@
{% for node in nodes %}
- {{ node.value }}
+ {{ node }}
{% endfor %}
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 %}
+
+{% 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 %}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {% 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 %}
+
+ {{ system_user }}
+
+
+
+
+ {% endfor %}
+
+
+
+
+
+
+
+
+
+
+{% 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 %}
+
+
+{% 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 %}
+
+{% 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' %}
+
+
+
+
+
+
+
+
+
+
+{% 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 %}#}
-{# #}
-{# {{ node }} #}
-{# #}
-{# #}
-{# #}
-{# #}
-{# {% endfor %}#}
-{# #}
-{#
#}
-{#
#}
-{#
#}
+ {% if system_user.protocol != 'rdp' %}
+
+
+
+ {% trans 'Command filter' %}
+
+
+
+
+
+ {% for cf in object.cmd_filters.all %}
+
+ {{ cf }}
+
+
+
+
+ {% endfor %}
+
+
+
+
+
+ {% 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 %}