Commit 5464c884 authored by ibuler's avatar ibuler

[Update] 修改swagger

parent 0db3e41b
......@@ -6,3 +6,4 @@ from .node import *
from .domain import *
from .cmd_filter import *
from .asset_user import *
from .gathered_user import *
......@@ -19,7 +19,7 @@ from rest_framework import generics
from rest_framework.response import Response
from orgs.mixins.api import OrgBulkModelViewSet
from common.mixins import IDInCacheFilterMixin
from common.mixins import CommonApiMixin
from common.utils import get_logger
from ..hands import IsOrgAdmin
from ..models import AdminUser, Asset
......
......@@ -5,9 +5,7 @@ import random
from rest_framework import generics
from rest_framework.response import Response
from django.utils.translation import ugettext_lazy as _
from django.shortcuts import get_object_or_404
from django.db.models import Q
from common.utils import get_logger, get_object_or_none
from common.permissions import IsOrgAdmin, IsOrgAdminOrAppUser
......@@ -16,7 +14,7 @@ from ..models import Asset, AdminUser, Node
from .. import serializers
from ..tasks import update_asset_hardware_info_manual, \
test_asset_connectivity_manual
from ..utils import LabelFilter
from ..filters import AssetByNodeFilterBackend, LabelFilterBackend
logger = get_logger(__file__)
......@@ -27,7 +25,7 @@ __all__ = [
]
class AssetViewSet(LabelFilter, OrgBulkModelViewSet):
class AssetViewSet(OrgBulkModelViewSet):
"""
API endpoint that allows Asset to be viewed or edited.
"""
......@@ -37,7 +35,7 @@ class AssetViewSet(LabelFilter, OrgBulkModelViewSet):
queryset = Asset.objects.all()
serializer_class = serializers.AssetSerializer
permission_classes = (IsOrgAdminOrAppUser,)
success_message = _("%(hostname)s was %(action)s successfully")
extra_filter_backends = [AssetByNodeFilterBackend, LabelFilterBackend]
def set_assets_node(self, assets):
if not isinstance(assets, list):
......@@ -54,30 +52,6 @@ class AssetViewSet(LabelFilter, OrgBulkModelViewSet):
assets = serializer.save()
self.set_assets_node(assets)
def filter_node(self, queryset):
node_id = self.request.query_params.get("node_id")
if not node_id:
return queryset
node = get_object_or_404(Node, id=node_id)
show_current_asset = self.request.query_params.get("show_current_asset") in ('1', 'true')
# 当前节点是顶层节点, 并且仅显示直接资产
if node.is_org_root() and show_current_asset:
queryset = queryset.filter(
Q(nodes=node_id) | Q(nodes__isnull=True)
).distinct()
# 当前节点是顶层节点,显示所有资产
elif node.is_org_root() and not show_current_asset:
return queryset
# 当前节点不是鼎城节点,只显示直接资产
elif not node.is_org_root() and show_current_asset:
queryset = queryset.filter(nodes=node)
else:
children = node.get_all_children(with_self=True)
queryset = queryset.filter(nodes__in=children).distinct()
return queryset
def filter_admin_user_id(self, queryset):
admin_user_id = self.request.query_params.get('admin_user_id')
if not admin_user_id:
......@@ -88,7 +62,6 @@ class AssetViewSet(LabelFilter, OrgBulkModelViewSet):
def filter_queryset(self, queryset):
queryset = super().filter_queryset(queryset)
queryset = self.filter_node(queryset)
queryset = self.filter_admin_user_id(queryset)
return queryset
......
......@@ -10,7 +10,7 @@ from django.http import Http404
from common.permissions import IsOrgAdminOrAppUser, NeedMFAVerify
from common.utils import get_object_or_none, get_logger
from common.mixins import IDInCacheFilterMixin
from common.mixins import CommonApiMixin
from ..backends import AssetUserManager
from ..models import Asset, Node, SystemUser, AdminUser
from .. import serializers
......@@ -52,7 +52,7 @@ class AssetUserSearchBackend(filters.BaseFilterBackend):
return _queryset
class AssetUserViewSet(IDInCacheFilterMixin, BulkModelViewSet):
class AssetUserViewSet(CommonApiMixin, BulkModelViewSet):
serializer_class = serializers.AssetUserSerializer
permission_classes = [IsOrgAdminOrAppUser]
http_method_names = ['get', 'post']
......
# -*- coding: utf-8 -*-
#
from orgs.mixins.api import OrgModelViewSet
from assets.models import GatheredUser
from common.permissions import IsOrgAdmin
from ..serializers import GatheredUserSerializer
__all__ = ['GatheredUserViewSet']
class GatheredUserViewSet(OrgModelViewSet):
queryset = GatheredUser.objects.all()
serializer_class = GatheredUserSerializer
permission_classes = [IsOrgAdmin]
filter_fields = ['asset', 'username', 'present']
search_fields = ['username', 'asset__ip', 'asset__hostname']
# -*- coding: utf-8 -*-
#
import coreapi
from rest_framework import filters
from django.db.models import Q
from common.utils import dict_get_any, is_uuid, get_object_or_none
from .models import Node, Label
class AssetByNodeFilterBackend(filters.BaseFilterBackend):
fields = ['node', 'all']
# def filter_node(self, queryset):
# node_id = self.request.query_params.get("node_id")
# if not node_id:
# return queryset
#
# node = get_object_or_404(Node, id=node_id)
# show_current_asset = self.request.query_params.get("show_current_asset") in ('1', 'true')
#
# # 当前节点是顶层节点, 并且仅显示直接资产
# if node.is_org_root() and show_current_asset:
# queryset = queryset.filter(
# Q(nodes=node_id) | Q(nodes__isnull=True)
# ).distinct()
# # 当前节点是顶层节点,显示所有资产
# elif node.is_org_root() and not show_current_asset:
# return queryset
# # 当前节点不是鼎城节点,只显示直接资产
# elif not node.is_org_root() and show_current_asset:
# queryset = queryset.filter(nodes=node)
# else:
# children = node.get_all_children(with_self=True)
# queryset = queryset.filter(nodes__in=children).distinct()
# return queryset
def get_schema_fields(self, view):
return [
coreapi.Field(
name=field, location='query', required=False,
type='string', example='', description=''
)
for field in self.fields
]
def filter_queryset(self, request, queryset, view):
node_id = dict_get_any(request.query_params, ['node', 'node_id'])
if not node_id:
return queryset
query_all_arg = request.query_params.get('all')
show_current_asset_arg = request.query_params.get('show_current_asset')
query_all = query_all_arg == '1'
if show_current_asset_arg is not None:
query_all = show_current_asset_arg != '1'
if is_uuid(node_id):
node = get_object_or_none(Node, id=node_id)
else:
node = get_object_or_none(Node, key=node_id)
if not node:
return queryset.none()
if query_all:
pattern = node.get_all_children_pattern(with_self=True)
else:
pattern = node.get_children_key_pattern(with_self=True)
return queryset.filter(nodes__key__regex=pattern)
class LabelFilterBackend(filters.BaseFilterBackend):
sep = '#'
query_arg = 'label'
def get_schema_fields(self, view):
example = self.sep.join(['os', 'linux'])
return [
coreapi.Field(
name=self.query_arg, location='query', required=False,
type='string', example=example, description=''
)
]
def get_query_labels(self, request):
labels_query = request.query_params.getlist(self.query_arg)
if not labels_query:
return None
q = None
for kv in labels_query:
if self.sep not in kv:
continue
key, value = kv.strip().split(self.sep)[:2]
if not all([key, value]):
continue
if q:
q |= Q(name=key, value=value)
else:
q = Q(name=key, value=value)
if not q:
return []
labels = Label.objects.filter(q, is_active=True)\
.values_list('id', flat=True)
return labels
def filter_queryset(self, request, queryset, view):
labels = self.get_query_labels(request)
if labels is None:
return queryset
if len(labels) == 0:
return queryset.none()
for label in labels:
queryset = queryset.filter(labels=label)
return queryset
# Generated by Django 2.1.7 on 2019-09-17 12:22
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('assets', '0038_auto_20190911_1634'),
]
operations = [
migrations.AddField(
model_name='authbook',
name='is_active',
field=models.BooleanField(default=True, verbose_name='Is active'),
),
]
# Generated by Django 2.1.7 on 2019-09-17 12:56
import django.core.validators
from django.db import migrations, models
import django.db.models.deletion
import uuid
class Migration(migrations.Migration):
dependencies = [
('assets', '0039_authbook_is_active'),
]
operations = [
migrations.AlterField(
model_name='adminuser',
name='username',
field=models.CharField(blank=True, db_index=True, max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'),
),
migrations.AlterField(
model_name='authbook',
name='username',
field=models.CharField(blank=True, db_index=True, max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'),
),
migrations.AlterField(
model_name='gateway',
name='username',
field=models.CharField(blank=True, db_index=True, max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'),
),
migrations.AlterField(
model_name='systemuser',
name='username',
field=models.CharField(blank=True, db_index=True, max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'),
),
]
# Generated by Django 2.1.7 on 2019-09-18 04:10
from django.db import migrations, models
import django.db.models.deletion
import uuid
class Migration(migrations.Migration):
dependencies = [
('assets', '0040_auto_20190917_2056'),
]
operations = [
migrations.CreateModel(
name='GatheredUser',
fields=[
('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('username', models.CharField(blank=True, db_index=True, max_length=32, verbose_name='Username')),
('present', models.BooleanField(default=True)),
('date_created', models.DateTimeField(auto_now_add=True, verbose_name='Date created')),
('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
('asset', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.Asset')),
],
options={'ordering': ['asset'], 'verbose_name': 'GatherUser'},
),
]
......@@ -9,3 +9,4 @@ from .cmd_filter import *
from .authbook import *
from .utils import *
from .authbook import *
from .gathered_user import *
......@@ -13,7 +13,7 @@ __all__ = ['AuthBook']
class AuthBookQuerySet(models.QuerySet):
def latest_version(self):
return self.filter(is_latest=True)
return self.filter(is_latest=True).filter(is_active=True)
class AuthBookManager(OrgManager):
......@@ -24,6 +24,7 @@ class AuthBook(AssetUser):
asset = models.ForeignKey('assets.Asset', on_delete=models.CASCADE, verbose_name=_('Asset'))
is_latest = models.BooleanField(default=False, verbose_name=_('Latest version'))
version = models.IntegerField(default=1, verbose_name=_('Version'))
is_active = models.BooleanField(default=True, verbose_name=_("Is active"))
objects = AuthBookManager.from_queryset(AuthBookQuerySet)()
backend = "db"
......@@ -34,25 +35,25 @@ class AuthBook(AssetUser):
class Meta:
verbose_name = _('AuthBook')
def _set_latest(self):
self._remove_pre_obj_latest()
def set_to_latest(self):
self.remove_pre_latest()
self.is_latest = True
self.save()
def _get_pre_obj(self):
def get_pre_latest(self):
pre_obj = self.__class__.objects.filter(
username=self.username, asset=self.asset
).latest_version().first()
return pre_obj
def _remove_pre_obj_latest(self):
pre_obj = self._get_pre_obj()
def remove_pre_latest(self):
pre_obj = self.get_pre_latest()
if pre_obj:
pre_obj.is_latest = False
pre_obj.save()
def _set_version(self):
pre_obj = self._get_pre_obj()
def set_version(self):
pre_obj = self.get_pre_latest()
if pre_obj:
self.version = pre_obj.version + 1
else:
......@@ -60,8 +61,8 @@ class AuthBook(AssetUser):
self.save()
def set_version_and_latest(self):
self._set_version()
self._set_latest()
self.set_version()
self.set_to_latest()
def get_related_assets(self):
return [self.asset]
......
......@@ -26,7 +26,7 @@ logger = get_logger(__file__)
class AssetUser(OrgModelMixin):
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
name = models.CharField(max_length=128, verbose_name=_('Name'))
username = models.CharField(max_length=32, blank=True, verbose_name=_('Username'), validators=[alphanumeric])
username = models.CharField(max_length=32, blank=True, verbose_name=_('Username'), validators=[alphanumeric], db_index=True)
password = fields.EncryptCharField(max_length=256, blank=True, null=True, verbose_name=_('Password'))
private_key = fields.EncryptTextField(blank=True, null=True, verbose_name=_('SSH private key'))
public_key = fields.EncryptTextField(blank=True, null=True, verbose_name=_('SSH public key'))
......
# -*- coding: utf-8 -*-
#
import uuid
from django.db import models
from django.utils.translation import ugettext_lazy as _
from orgs.mixins.models import OrgModelMixin
__all__ = ['GatheredUser']
class GatheredUser(OrgModelMixin):
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
asset = models.ForeignKey('assets.Asset', on_delete=models.CASCADE)
username = models.CharField(max_length=32, blank=True, db_index=True,
verbose_name=_('Username'))
present = models.BooleanField(default=True)
date_created = models.DateTimeField(auto_now_add=True,
verbose_name=_("Date created"))
date_updated = models.DateTimeField(auto_now=True,
verbose_name=_("Date updated"))
@property
def hostname(self):
return self.asset.hostname
@property
def ip(self):
return self.asset.ip
class Meta:
verbose_name = _('GatherUser')
ordering = ['asset']
def __str__(self):
return '{}: {}'.format(self.asset.hostname, self.username)
......@@ -116,16 +116,24 @@ class FamilyMixin:
def all_children(self):
return self.get_all_children(with_self=False)
def get_children(self, with_self=False):
def get_children_key_pattern(self, with_self=False):
pattern = r'^{0}:[0-9]+$'.format(self.key)
if with_self:
pattern += r'|^{0}$'.format(self.key)
return pattern
def get_children(self, with_self=False):
pattern = self.get_children_key_pattern(with_self=with_self)
return Node.objects.filter(key__regex=pattern)
def get_all_children(self, with_self=False):
def get_all_children_pattern(self, with_self=False):
pattern = r'^{0}:'.format(self.key)
if with_self:
pattern += r'|^{0}$'.format(self.key)
return pattern
def get_all_children(self, with_self=False):
pattern = self.get_all_children_pattern(with_self=with_self)
children = Node.objects.filter(key__regex=pattern)
return children
......
......@@ -9,3 +9,4 @@ from .node import *
from .domain import *
from .cmd_filter import *
from .asset_user import *
from .gathered_user import *
......@@ -53,6 +53,7 @@ class AssetUserSerializer(AuthSerializerMixin, BulkOrgResourceModelSerializer):
if not validated_data.get("name") and validated_data.get("username"):
validated_data["name"] = validated_data["username"]
instance = AssetUserManager.create(**validated_data)
instance.set_version_and_latest()
return instance
......
# -*- coding: utf-8 -*-
#
from ..models import GatheredUser
from orgs.mixins.serializers import OrgResourceModelSerializerMixin
class GatheredUserSerializer(OrgResourceModelSerializerMixin):
class Meta:
model = GatheredUser
fields = [
'id', 'asset', 'hostname', 'ip', 'username',
'present', 'date_created', 'date_updated'
]
read_only_fields = fields
......@@ -9,7 +9,7 @@ from django.dispatch import receiver
from common.utils import get_logger
from common.decorator import on_transaction_commit
from .models import Asset, SystemUser, Node, AuthBook
from .models import Asset, SystemUser, Node
from .tasks import (
update_assets_hardware_info_util,
test_asset_connectivity_util,
......@@ -190,10 +190,3 @@ def on_asset_nodes_remove(sender, instance=None, action='', model=None,
def on_node_update_or_created(sender, **kwargs):
# 刷新节点
Node.refresh_nodes()
@receiver(post_save, sender=AuthBook)
def on_auth_book_created(sender, instance=None, created=False, **kwargs):
if created:
logger.debug('Receive create auth book object signal.')
instance.set_version_and_latest()
......@@ -103,7 +103,7 @@ def update_assets_hardware_info_util(assets, task_name=None):
)
result = task.run()
set_assets_hardware_info(assets, result)
return result
return True
@shared_task(queue="ansible")
......
# ~*~ coding: utf-8 ~*~
import re
from collections import defaultdict
from celery import shared_task
from django.utils.translation import ugettext as _
from orgs.utils import tmp_to_org
from common.utils import get_logger
from ..models import GatheredUser, Node
from .utils import clean_hosts
from . import const
__all__ = ['gather_asset_users', 'gather_nodes_asset_users']
logger = get_logger(__name__)
space = re.compile('\s+')
ignore_login_shell = re.compile(r'nologin$|sync$|shutdown$|halt$')
def parse_linux_result_to_users(result):
task_result = {}
for task_name, raw in result.items():
res = raw.get('ansible_facts', {}).get('getent_passwd')
if res:
task_result = res
break
if not task_result or not isinstance(task_result, dict):
return []
users = []
for username, attr in task_result.items():
if ignore_login_shell.search(attr[-1]):
continue
users.append(username)
return users
def parse_windows_result_to_users(result):
task_result = []
for task_name, raw in result.items():
res = raw.get('stdout_lines', {})
if res:
task_result = res
break
if not task_result:
return []
users = []
for i in range(4):
task_result.pop(0)
for i in range(2):
task_result.pop()
for line in task_result:
user = space.split(line)
if user[0]:
users.append(user[0])
return users
def add_asset_users(assets, results):
assets_map = {a.hostname: a for a in assets}
parser_map = {
'linux': parse_linux_result_to_users,
'windows': parse_windows_result_to_users
}
assets_users_map = {}
for platform, platform_results in results.items():
for hostname, res in platform_results.items():
parse = parser_map.get(platform)
users = parse(res)
logger.debug('Gathered host users: {} {}'.format(hostname, users))
asset = assets_map.get(hostname)
if not asset:
continue
assets_users_map[asset] = users
for asset, users in assets_users_map.items():
with tmp_to_org(asset.org_id):
GatheredUser.objects.filter(asset=asset, present=True)\
.update(present=False)
for username in users:
defaults = {'asset': asset, 'username': username, 'present': True}
GatheredUser.objects.update_or_create(
defaults=defaults, asset=asset, username=username,
)
@shared_task(queue="ansible")
def gather_asset_all_users(assets, task_name=None):
def gather_asset_users(assets, task_name=None):
from ops.utils import update_or_create_ansible_task
if task_name is None:
task_name = _("Gather assets users")
assets = clean_hosts(assets)
if not assets:
return
hosts_category = {
'linux': {
'hosts': [],
......@@ -38,5 +123,12 @@ def gather_asset_all_users(assets, task_name=None):
)
raw, summary = task.run()
results[k].update(raw['ok'])
return results
add_asset_users(assets, results)
@shared_task(queue="ansible")
def gather_nodes_asset_users(nodes_key):
assets = Node.get_nodes_all_assets(nodes_key)
assets_groups_by_100 = [assets[i:i+100] for i in range(0, len(assets), 100)]
for _assets in assets_groups_by_100:
gather_asset_users(_assets)
......@@ -85,7 +85,7 @@
<button data-toggle="dropdown" class="btn btn-default btn-sm dropdown-toggle">{% trans 'Label' %} <span class="caret"></span></button>
<ul class="dropdown-menu labels">
{% for label in labels %}
<li><a style="font-weight: bolder">{{ label.name }}:{{ label.value }}</a></li>
<li><a style="font-weight: bolder">{{ label.name }}#{{ label.value }}</a></li>
{% endfor %}
</ul>
</div>
......@@ -171,9 +171,13 @@ function initTable() {
],
ajax_url: '{% url "api-assets:asset-list" %}',
columns: [
{data: "id"}, {data: "hostname" }, {data: "ip" },
{data: "id"}, {data: "hostname"}, {data: "ip"},
{data: "cpu_cores", orderable: false},
{data: "connectivity", orderable: false}, {data: "id", orderable: false }
{
data: "connectivity",
orderable: false,
width: '60px'
}, {data: "id", orderable: false}
],
op_html: $('#actions').html()
};
......@@ -271,7 +275,7 @@ $(document).ready(function(){
setAssetModalOptions(modalOption);
})
.on('click', '.labels li', function () {
var val = $(this).text();
var val = 'label:' + $(this).text();
$("#asset_list_table_filter input").val(val);
asset_table.search(val).draw();
})
......
......@@ -21,6 +21,7 @@ router.register(r'gateways', api.GatewayViewSet, 'gateway')
router.register(r'cmd-filters', api.CommandFilterViewSet, 'cmd-filter')
router.register(r'asset-users', api.AssetUserViewSet, 'asset-user')
router.register(r'asset-users-info', api.AssetUserExportViewSet, 'asset-user-info')
router.register(r'gathered-users', api.GatheredUserViewSet, 'gathered-user')
cmd_filter_router = routers.NestedDefaultRouter(router, r'cmd-filters', lookup='filter')
cmd_filter_router.register(r'rules', api.CommandFilterRuleViewSet, 'cmd-filter-rule')
......
......@@ -24,37 +24,6 @@ def get_system_user_by_id(id):
return system_user
class LabelFilterMixin:
def get_filter_labels_ids(self):
query_params = self.request.query_params
query_keys = query_params.keys()
all_label_keys = Label.objects.values_list('name', flat=True)
valid_keys = set(all_label_keys) & set(query_keys)
if not valid_keys:
return []
labels_query = [
{"name": key, "value": query_params[key]}
for key in valid_keys
]
args = [Q(**kwargs) for kwargs in labels_query]
args = reduce(lambda x, y: x | y, args)
labels_id = Label.objects.filter(args).values_list('id', flat=True)
return labels_id
class LabelFilter(LabelFilterMixin):
def filter_queryset(self, queryset):
queryset = super().filter_queryset(queryset)
labels_ids = self.get_filter_labels_ids()
if not labels_ids:
return queryset
for labels_id in labels_ids:
queryset = queryset.filter(labels=labels_id)
return queryset
class TreeService(Tree):
tag_sep = ' / '
cache_key = '_NODE_FULL_TREE'
......
# -*- coding: utf-8 -*-
#
import coreapi
from rest_framework import filters
from rest_framework.fields import DateTimeField
from rest_framework.serializers import ValidationError
from django.core.cache import cache
import logging
__all__ = ["DatetimeRangeFilter"]
from . import const
__all__ = ["DatetimeRangeFilter", "IDSpmFilter", "CustomFilter"]
class DatetimeRangeFilter(filters.BaseFilterBackend):
......@@ -40,3 +44,50 @@ class DatetimeRangeFilter(filters.BaseFilterBackend):
if kwargs:
queryset = queryset.filter(**kwargs)
return queryset
class IDSpmFilter(filters.BaseFilterBackend):
def get_schema_fields(self, view):
return [
coreapi.Field(
name='spm', location='query', required=False,
type='string', example='',
description='Pre post objects id get spm id, then using filter'
)
]
def filter_queryset(self, request, queryset, view):
spm = request.query_params.get('spm')
if not spm:
return queryset
cache_key = const.KEY_CACHE_RESOURCES_ID.format(spm)
resources_id = cache.get(cache_key)
if not resources_id or not isinstance(resources_id, list):
queryset = queryset.none()
return queryset
queryset = queryset.filter(id__in=resources_id)
return queryset
class CustomFilter(filters.BaseFilterBackend):
custom_filter_fields = [] # ["node", "asset"]
def get_schema_fields(self, view):
fields = []
defaults = dict(
location='query', required=False,
type='string', example='',
description=''
)
for field in self.custom_filter_fields:
if isinstance(field, str):
defaults['name'] = field
elif isinstance(field, dict):
defaults.update(field)
else:
continue
fields.append(coreapi.Field(**defaults))
return fields
def filter_queryset(self, request, queryset, view):
return queryset
# -*- coding: utf-8 -*-
#
from django.http import JsonResponse
from django.core.cache import cache
from django.utils.translation import ugettext_lazy as _
from django.contrib import messages
from rest_framework.settings import api_settings
from ..const import KEY_CACHE_RESOURCES_ID
from ..filters import IDSpmFilter, CustomFilter
__all__ = [
"JSONResponseMixin", "IDInCacheFilterMixin", "IDExportFilterMixin",
"IDInFilterMixin", "ApiMessageMixin"
"JSONResponseMixin", "CommonApiMixin",
"IDSpmFilterMixin", "CommonApiMixin",
]
......@@ -20,69 +18,31 @@ class JSONResponseMixin(object):
return JsonResponse(context)
class IDInFilterMixin(object):
def filter_queryset(self, queryset):
queryset = super(IDInFilterMixin, self).filter_queryset(queryset)
id_list = self.request.query_params.get('id__in')
if id_list:
import json
try:
ids = json.loads(id_list)
except Exception as e:
return queryset
if isinstance(ids, list):
queryset = queryset.filter(id__in=ids)
return queryset
class IDSpmFilterMixin:
def get_filter_backends(self):
backends = super().get_filter_backends()
backends.append(IDSpmFilter)
return backends
class IDInCacheFilterMixin(object):
def filter_queryset(self, queryset):
queryset = super().filter_queryset(queryset)
spm = self.request.query_params.get('spm')
if not spm:
return queryset
cache_key = KEY_CACHE_RESOURCES_ID.format(spm)
resources_id = cache.get(cache_key)
if not resources_id or not isinstance(resources_id, list):
queryset = queryset.none()
return queryset
queryset = queryset.filter(id__in=resources_id)
return queryset
class ExtraFilterFieldsMixin:
default_added_filters = [CustomFilter, IDSpmFilter]
filter_backends = api_settings.DEFAULT_FILTER_BACKENDS
extra_filter_fields = []
extra_filter_backends = []
def get_filter_backends(self):
if self.filter_backends != self.__class__.filter_backends:
return self.filter_backends
return list(self.filter_backends) + \
self.default_added_filters + \
list(self.extra_filter_backends)
class IDExportFilterMixin(object):
def filter_queryset(self, queryset):
# 下载导入模版
if self.request.query_params.get('template') == 'import':
return []
else:
return super(IDExportFilterMixin, self).filter_queryset(queryset)
class ApiMessageMixin:
success_message = _("%(name)s was %(action)s successfully")
_action_map = {"create": _("create"), "update": _("update")}
for backend in self.get_filter_backends():
queryset = backend().filter_queryset(self.request, queryset, self)
return queryset
def get_success_message(self, cleaned_data):
if not isinstance(cleaned_data, dict):
return ''
data = {k: v for k, v in cleaned_data.items()}
action = getattr(self, "action", "create")
data["action"] = self._action_map.get(action)
try:
message = self.success_message % data
except:
message = ''
return message
def dispatch(self, request, *args, **kwargs):
resp = super().dispatch(request, *args, **kwargs)
if request.method.lower() in ("get", "delete", "patch"):
return resp
if resp.status_code >= 400:
return resp
message = self.get_success_message(resp.data)
if message:
messages.success(request, message)
return resp
class CommonApiMixin(ExtraFilterFieldsMixin):
pass
......@@ -8,7 +8,6 @@ import datetime
import uuid
from functools import wraps
import time
import copy
import ipaddress
......@@ -199,3 +198,18 @@ def timeit(func):
logger.debug(msg)
return result
return wrapper
def group_obj_by_count(objs, count=50):
objs_grouped = [
objs[i:i + count] for i in range(0, len(objs), count)
]
return objs_grouped
def dict_get_any(d, keys):
for key in keys:
value = d.get(key)
if value:
return value
return None
......@@ -33,6 +33,21 @@ class CustomSwaggerAutoSchema(SwaggerAutoSchema):
operation.summary = operation.operation_id
return operation
def get_filter_parameters(self):
if not self.should_filter():
return []
fields = []
if hasattr(self.view, 'get_filter_backends'):
backends = self.view.get_filter_backends()
elif hasattr(self.view, 'filter_backends'):
backends = self.view.filter_backends
else:
backends = []
for filter_backend in backends:
fields += self.probe_inspectors(self.filter_inspectors, 'get_filter_parameters', filter_backend()) or []
return fields
def get_swagger_view(version='v1'):
from .urls import api_v1, api_v2
......
......@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Jumpserver 0.3.3\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-09-12 18:01+0800\n"
"POT-Creation-Date: 2019-09-18 12:53+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: ibuler <ibuler@qq.com>\n"
"Language-Team: Jumpserver team<ibuler@qq.com>\n"
......@@ -71,13 +71,13 @@ msgstr "目标地址"
msgid "Operating parameter"
msgstr "运行参数"
#: applications/forms/remote_app.py:104 applications/models/remote_app.py:23
#: applications/forms/remote_app.py:100 applications/models/remote_app.py:23
#: applications/templates/applications/remote_app_detail.html:57
#: applications/templates/applications/remote_app_list.html:22
#: applications/templates/applications/user_remote_app_list.html:18
#: assets/forms/domain.py:15 assets/forms/label.py:13
#: assets/models/asset.py:295 assets/models/authbook.py:24
#: assets/serializers/admin_user.py:32 assets/serializers/asset_user.py:81
#: assets/serializers/admin_user.py:32 assets/serializers/asset_user.py:82
#: assets/serializers/system_user.py:31
#: assets/templates/assets/admin_user_list.html:46
#: assets/templates/assets/domain_detail.html:60
......@@ -96,40 +96,20 @@ msgstr "运行参数"
#: terminal/templates/terminal/session_list.html:28
#: terminal/templates/terminal/session_list.html:72
#: xpack/plugins/change_auth_plan/forms.py:121
#: xpack/plugins/change_auth_plan/models.py:413
#: xpack/plugins/change_auth_plan/models.py:412
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:46
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:54
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:13
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:14
#: xpack/plugins/cloud/models.py:310
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:63
#: xpack/plugins/gathered_user/forms.py:13
#: xpack/plugins/gathered_user/forms.py:15
#: xpack/plugins/orgs/templates/orgs/org_list.html:16
#: xpack/plugins/vault/forms.py:13 xpack/plugins/vault/forms.py:15
msgid "Asset"
msgstr "资产"
#: applications/forms/remote_app.py:107 applications/models/remote_app.py:27
#: applications/templates/applications/remote_app_detail.html:61
#: applications/templates/applications/remote_app_list.html:23
#: applications/templates/applications/user_remote_app_list.html:19
#: assets/models/user.py:168 assets/templates/assets/user_asset_list.html:52
#: audits/models.py:20 audits/templates/audits/ftp_log_list.html:52
#: audits/templates/audits/ftp_log_list.html:75
#: perms/forms/asset_permission.py:85 perms/models/asset_permission.py:80
#: perms/templates/perms/asset_permission_detail.html:140
#: perms/templates/perms/asset_permission_list.html:54
#: perms/templates/perms/asset_permission_list.html:75
#: perms/templates/perms/asset_permission_list.html:127 templates/_nav.html:25
#: terminal/backends/command/models.py:14 terminal/models.py:156
#: terminal/templates/terminal/command_list.html:31
#: terminal/templates/terminal/command_list.html:67
#: terminal/templates/terminal/session_list.html:29
#: terminal/templates/terminal/session_list.html:73
#: users/templates/users/_granted_assets.html:27
#: xpack/plugins/orgs/templates/orgs/org_list.html:19
msgid "System user"
msgstr "系统用户"
#: applications/models/remote_app.py:21
#: applications/templates/applications/remote_app_detail.html:53
#: applications/templates/applications/remote_app_list.html:20
......@@ -166,7 +146,7 @@ msgstr "系统用户"
#: settings/templates/settings/terminal_setting.html:105 terminal/models.py:22
#: terminal/models.py:258 terminal/templates/terminal/terminal_detail.html:43
#: terminal/templates/terminal/terminal_list.html:29 users/models/group.py:14
#: users/models/user.py:330 users/templates/users/_select_user_modal.html:13
#: users/models/user.py:373 users/templates/users/_select_user_modal.html:13
#: users/templates/users/user_detail.html:63
#: users/templates/users/user_group_detail.html:55
#: users/templates/users/user_group_list.html:35
......@@ -174,7 +154,7 @@ msgstr "系统用户"
#: users/templates/users/user_profile.html:51
#: users/templates/users/user_pubkey_update.html:57
#: xpack/plugins/change_auth_plan/forms.py:104
#: xpack/plugins/change_auth_plan/models.py:61
#: xpack/plugins/change_auth_plan/models.py:60
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:61
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:12
#: xpack/plugins/cloud/models.py:59 xpack/plugins/cloud/models.py:144
......@@ -187,24 +167,24 @@ msgstr "系统用户"
msgid "Name"
msgstr "名称"
#: applications/models/remote_app.py:32
#: applications/templates/applications/remote_app_detail.html:65
#: applications/models/remote_app.py:28
#: applications/templates/applications/remote_app_detail.html:61
#: applications/templates/applications/remote_app_list.html:21
#: applications/templates/applications/user_remote_app_list.html:17
msgid "App type"
msgstr "应用类型"
#: applications/models/remote_app.py:36
#: applications/templates/applications/remote_app_detail.html:69
#: applications/models/remote_app.py:32
#: applications/templates/applications/remote_app_detail.html:65
msgid "App path"
msgstr "应用路径"
#: applications/models/remote_app.py:40
#: applications/models/remote_app.py:36
msgid "Parameters"
msgstr "参数"
#: applications/models/remote_app.py:43
#: applications/templates/applications/remote_app_detail.html:77
#: applications/models/remote_app.py:39
#: applications/templates/applications/remote_app_detail.html:73
#: assets/models/asset.py:174 assets/models/base.py:36
#: assets/models/cluster.py:28 assets/models/cmd_filter.py:25
#: assets/models/cmd_filter.py:58 assets/models/group.py:21
......@@ -213,13 +193,13 @@ msgstr "参数"
#: 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:14
#: ops/templates/ops/adhoc_detail.html:86 orgs/models.py:15
#: perms/models/base.py:54
#: perms/templates/perms/asset_permission_detail.html:98
#: perms/templates/perms/remote_app_permission_detail.html:90
#: users/models/user.py:371 users/serializers/v1.py:119
#: users/models/user.py:414 users/serializers/v1.py:141
#: users/templates/users/user_detail.html:111
#: xpack/plugins/change_auth_plan/models.py:106
#: xpack/plugins/change_auth_plan/models.py:105
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:113
#: xpack/plugins/cloud/models.py:80 xpack/plugins/cloud/models.py:179
msgid "Created by"
......@@ -227,17 +207,17 @@ msgstr "创建者"
# msgid "Created by"
# msgstr "创建者"
#: applications/models/remote_app.py:46
#: applications/templates/applications/remote_app_detail.html:73
#: applications/models/remote_app.py:42
#: applications/templates/applications/remote_app_detail.html:69
#: assets/models/asset.py:175 assets/models/base.py:34
#: assets/models/cluster.py:26 assets/models/domain.py:23
#: assets/models/group.py:22 assets/models/label.py:25
#: assets/templates/assets/admin_user_detail.html:64
#: assets/models/gathered_user.py:19 assets/models/group.py:22
#: assets/models/label.py:25 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:64
#: orgs/models.py:15 perms/models/base.py:55
#: orgs/models.py:16 perms/models/base.py:55
#: perms/templates/perms/asset_permission_detail.html:94
#: perms/templates/perms/remote_app_permission_detail.html:86
#: terminal/templates/terminal/terminal_detail.html:59 users/models/group.py:17
......@@ -252,10 +232,10 @@ msgstr "创建日期"
# msgid "Date created"
# msgstr "创建日期"
#: applications/models/remote_app.py:49
#: applications/templates/applications/remote_app_detail.html:81
#: applications/templates/applications/remote_app_list.html:24
#: applications/templates/applications/user_remote_app_list.html:20
#: applications/models/remote_app.py:45
#: applications/templates/applications/remote_app_detail.html:77
#: applications/templates/applications/remote_app_list.html:23
#: applications/templates/applications/user_remote_app_list.html:19
#: assets/models/asset.py:176 assets/models/base.py:33
#: assets/models/cluster.py:29 assets/models/cmd_filter.py:22
#: assets/models/cmd_filter.py:55 assets/models/domain.py:21
......@@ -271,16 +251,16 @@ msgstr "创建日期"
#: assets/templates/assets/domain_list.html:28
#: assets/templates/assets/system_user_detail.html:104
#: assets/templates/assets/system_user_list.html:59 ops/models/adhoc.py:43
#: orgs/models.py:16 perms/models/base.py:56
#: orgs/models.py:17 perms/models/base.py:56
#: perms/templates/perms/asset_permission_detail.html:102
#: perms/templates/perms/remote_app_permission_detail.html:94
#: settings/models.py:34 terminal/models.py:32
#: terminal/templates/terminal/terminal_detail.html:63 users/models/group.py:15
#: users/models/user.py:363 users/templates/users/user_detail.html:129
#: users/models/user.py:406 users/templates/users/user_detail.html:129
#: users/templates/users/user_group_detail.html:67
#: users/templates/users/user_group_list.html:37
#: users/templates/users/user_profile.html:138
#: xpack/plugins/change_auth_plan/models.py:102
#: xpack/plugins/change_auth_plan/models.py:101
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:117
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:19
#: xpack/plugins/cloud/models.py:77 xpack/plugins/cloud/models.py:173
......@@ -293,18 +273,18 @@ msgstr "创建日期"
msgid "Comment"
msgstr "备注"
#: applications/models/remote_app.py:53 perms/forms/remote_app_permission.py:37
#: applications/models/remote_app.py:49 perms/forms/remote_app_permission.py:37
#: perms/models/remote_app_permission.py:15
#: perms/templates/perms/remote_app_permission_create_update.html:48
#: perms/templates/perms/remote_app_permission_detail.html:27
#: perms/templates/perms/remote_app_permission_list.html:17
#: perms/templates/perms/remote_app_permission_remote_app.html:26
#: perms/templates/perms/remote_app_permission_user.html:26
#: templates/_nav.html:36 templates/_nav.html:48 templates/_nav_user.html:16
#: templates/_nav.html:60 templates/_nav.html:76 templates/_nav_user.html:16
msgid "RemoteApp"
msgstr "远程应用"
#: applications/templates/applications/remote_app_create_update.html:56
#: applications/templates/applications/remote_app_create_update.html:55
#: assets/templates/assets/_system_user.html:75
#: assets/templates/assets/admin_user_create_update.html:45
#: assets/templates/assets/asset_bulk_update.html:23
......@@ -315,7 +295,7 @@ msgstr "远程应用"
#: assets/templates/assets/gateway_create_update.html:58
#: assets/templates/assets/label_create_update.html:18
#: perms/templates/perms/asset_permission_create_update.html:83
#: perms/templates/perms/remote_app_permission_create_update.html:83
#: perms/templates/perms/remote_app_permission_create_update.html:84
#: settings/templates/settings/basic_setting.html:64
#: settings/templates/settings/command_storage_create.html:79
#: settings/templates/settings/email_content_setting.html:54
......@@ -336,12 +316,13 @@ msgstr "远程应用"
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:71
#: xpack/plugins/cloud/templates/cloud/account_create_update.html:33
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:53
#: xpack/plugins/gathered_user/templates/gathered_user/vault_create.html:45
#: xpack/plugins/interface/templates/interface/interface.html:72
#: xpack/plugins/vault/templates/vault/vault_create.html:45
msgid "Reset"
msgstr "重置"
#: applications/templates/applications/remote_app_create_update.html:58
#: applications/templates/applications/remote_app_create_update.html:57
#: assets/templates/assets/_system_user.html:76
#: assets/templates/assets/admin_user_create_update.html:46
#: assets/templates/assets/asset_bulk_update.html:24
......@@ -354,7 +335,7 @@ msgstr "重置"
#: assets/templates/assets/label_create_update.html:19
#: audits/templates/audits/login_log_list.html:95
#: perms/templates/perms/asset_permission_create_update.html:84
#: perms/templates/perms/remote_app_permission_create_update.html:84
#: perms/templates/perms/remote_app_permission_create_update.html:85
#: settings/templates/settings/basic_setting.html:65
#: settings/templates/settings/command_storage_create.html:80
#: settings/templates/settings/email_content_setting.html:55
......@@ -374,6 +355,7 @@ msgstr "重置"
#: users/templates/users/user_profile_update.html:68
#: users/templates/users/user_pubkey_update.html:81
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:72
#: xpack/plugins/gathered_user/templates/gathered_user/vault_create.html:46
#: xpack/plugins/interface/templates/interface/interface.html:74
#: xpack/plugins/vault/templates/vault/vault_create.html:46
msgid "Submit"
......@@ -406,7 +388,7 @@ msgid "Detail"
msgstr "详情"
#: applications/templates/applications/remote_app_detail.html:21
#: applications/templates/applications/remote_app_list.html:56
#: applications/templates/applications/remote_app_list.html:54
#: assets/templates/assets/_asset_user_list.html:69
#: assets/templates/assets/admin_user_detail.html:24
#: assets/templates/assets/admin_user_list.html:26
......@@ -453,7 +435,7 @@ msgid "Update"
msgstr "更新"
#: applications/templates/applications/remote_app_detail.html:25
#: applications/templates/applications/remote_app_list.html:57
#: applications/templates/applications/remote_app_list.html:55
#: assets/templates/assets/admin_user_detail.html:28
#: assets/templates/assets/admin_user_list.html:112
#: assets/templates/assets/asset_detail.html:31
......@@ -511,8 +493,8 @@ msgstr "下载应用加载器"
msgid "Create RemoteApp"
msgstr "创建远程应用"
#: applications/templates/applications/remote_app_list.html:25
#: applications/templates/applications/user_remote_app_list.html:21
#: applications/templates/applications/remote_app_list.html:24
#: applications/templates/applications/user_remote_app_list.html:20
#: assets/models/cmd_filter.py:54
#: assets/templates/assets/_asset_user_list.html:20
#: assets/templates/assets/admin_user_list.html:51
......@@ -550,7 +532,7 @@ msgstr "创建远程应用"
msgid "Action"
msgstr "动作"
#: applications/templates/applications/user_remote_app_list.html:57
#: applications/templates/applications/user_remote_app_list.html:52
#: assets/templates/assets/user_asset_list.html:32
#: perms/models/asset_permission.py:30
msgid "Connect"
......@@ -558,7 +540,7 @@ msgstr "连接"
#: applications/views/remote_app.py:31 applications/views/remote_app.py:47
#: applications/views/remote_app.py:70 applications/views/remote_app.py:89
#: templates/_nav.html:33
#: templates/_nav.html:57
msgid "Applications"
msgstr "应用管理"
......@@ -595,20 +577,6 @@ msgstr "更新节点资产硬件信息: {}"
msgid "Test if the assets under the node are connectable: {}"
msgstr "测试节点下资产是否可连接: {}"
#: assets/const.py:77 assets/models/utils.py:43
msgid "Unreachable"
msgstr "不可达"
#: assets/const.py:78 assets/models/utils.py:44
#: assets/templates/assets/asset_list.html:99
msgid "Reachable"
msgstr "可连接"
#: assets/const.py:79 assets/models/utils.py:45 authentication/utils.py:13
#: xpack/plugins/license/models.py:78
msgid "Unknown"
msgstr "未知"
#: assets/forms/asset.py:24 assets/models/asset.py:140
#: assets/models/domain.py:50
#: assets/templates/assets/domain_gateway_list.html:69
......@@ -621,14 +589,14 @@ msgstr "端口"
#: assets/templates/assets/asset_detail.html:198
#: assets/templates/assets/system_user_assets.html:83
#: perms/models/asset_permission.py:79
#: xpack/plugins/change_auth_plan/models.py:72
#: xpack/plugins/change_auth_plan/models.py:71
msgid "Nodes"
msgstr "节点"
#: assets/forms/asset.py:58 assets/forms/asset.py:104
#: assets/models/asset.py:149 assets/models/cluster.py:19
#: assets/models/user.py:68 assets/templates/assets/asset_detail.html:76
#: templates/_nav.html:24 xpack/plugins/cloud/models.py:161
#: templates/_nav.html:44 xpack/plugins/cloud/models.py:161
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:68
#: xpack/plugins/orgs/templates/orgs/org_list.html:18
msgid "Admin user"
......@@ -704,7 +672,7 @@ msgid "SSH gateway support proxy SSH,RDP,VNC"
msgstr "SSH网关,支持代理SSH,RDP和VNC"
#: assets/forms/domain.py:74 assets/forms/user.py:75 assets/forms/user.py:95
#: assets/models/base.py:29
#: assets/models/base.py:29 assets/models/gathered_user.py:16
#: assets/templates/assets/_asset_user_auth_update_modal.html:15
#: assets/templates/assets/_asset_user_auth_view_modal.html:21
#: assets/templates/assets/_asset_user_list.html:16
......@@ -720,17 +688,18 @@ msgstr "SSH网关,支持代理SSH,RDP和VNC"
#: perms/templates/perms/asset_permission_user.html:55
#: perms/templates/perms/remote_app_permission_user.html:54
#: settings/templates/settings/_ldap_list_users_modal.html:30 users/forms.py:14
#: users/models/user.py:328 users/templates/users/_select_user_modal.html:14
#: users/models/user.py:371 users/templates/users/_select_user_modal.html:14
#: users/templates/users/user_detail.html:67
#: users/templates/users/user_list.html:36
#: users/templates/users/user_profile.html:47
#: xpack/plugins/change_auth_plan/forms.py:106
#: xpack/plugins/change_auth_plan/models.py:63
#: xpack/plugins/change_auth_plan/models.py:409
#: xpack/plugins/change_auth_plan/models.py:62
#: xpack/plugins/change_auth_plan/models.py:408
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:65
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:53
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:12
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:13
#: xpack/plugins/gathered_user/templates/gathered_user/gathered_user_list.html:74
msgid "Username"
msgstr "用户名"
......@@ -739,7 +708,7 @@ msgid "Password or private key passphrase"
msgstr "密码或密钥密码"
#: assets/forms/user.py:26 assets/models/base.py:30
#: assets/serializers/asset_user.py:62
#: assets/serializers/asset_user.py:63
#: assets/templates/assets/_asset_user_auth_update_modal.html:21
#: assets/templates/assets/_asset_user_auth_view_modal.html:27
#: authentication/forms.py:15
......@@ -752,14 +721,14 @@ msgstr "密码或密钥密码"
#: users/templates/users/user_profile_update.html:41
#: users/templates/users/user_pubkey_update.html:41
#: users/templates/users/user_update.html:20
#: xpack/plugins/change_auth_plan/models.py:93
#: xpack/plugins/change_auth_plan/models.py:264
#: xpack/plugins/change_auth_plan/models.py:92
#: xpack/plugins/change_auth_plan/models.py:263
msgid "Password"
msgstr "密码"
#: assets/forms/user.py:29 assets/serializers/asset_user.py:70
#: assets/forms/user.py:29 assets/serializers/asset_user.py:71
#: assets/templates/assets/_asset_user_auth_update_modal.html:27
#: users/models/user.py:357
#: users/models/user.py:400
msgid "Private key"
msgstr "ssh私钥"
......@@ -811,6 +780,7 @@ msgstr "使用逗号分隔多个命令,如: /bin/whoami,/sbin/ifconfig"
#: perms/templates/perms/asset_permission_asset.html:58 settings/forms.py:140
#: users/templates/users/_granted_assets.html:26
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:51
#: xpack/plugins/gathered_user/templates/gathered_user/gathered_user_list.html:73
msgid "IP"
msgstr "IP"
......@@ -826,6 +796,7 @@ msgstr "IP"
#: perms/templates/perms/asset_permission_list.html:73 settings/forms.py:139
#: users/templates/users/_granted_assets.html:25
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:50
#: xpack/plugins/gathered_user/templates/gathered_user/gathered_user_list.html:72
msgid "Hostname"
msgstr "主机名"
......@@ -841,7 +812,7 @@ msgstr "协议"
#: assets/models/asset.py:142 assets/serializers/asset.py:63
#: assets/templates/assets/asset_create.html:24
#: assets/templates/assets/user_asset_list.html:50
#: perms/serializers/user_permission.py:38
#: perms/serializers/user_permission.py:48
msgid "Protocols"
msgstr "协议组"
......@@ -850,9 +821,9 @@ msgstr "协议组"
msgid "Platform"
msgstr "系统平台"
#: assets/models/asset.py:146 assets/models/cmd_filter.py:21
#: assets/models/domain.py:54 assets/models/label.py:22
#: assets/templates/assets/asset_detail.html:112
#: assets/models/asset.py:146 assets/models/authbook.py:27
#: assets/models/cmd_filter.py:21 assets/models/domain.py:54
#: assets/models/label.py:22 assets/templates/assets/asset_detail.html:112
msgid "Is active"
msgstr "激活"
......@@ -922,7 +893,7 @@ msgid "Hostname raw"
msgstr "主机名原始"
#: assets/models/asset.py:173 assets/templates/assets/asset_create.html:46
#: assets/templates/assets/asset_detail.html:224 templates/_nav.html:26
#: assets/templates/assets/asset_detail.html:224 templates/_nav.html:46
msgid "Labels"
msgstr "标签管理"
......@@ -938,22 +909,24 @@ msgstr "最新版本"
msgid "Version"
msgstr "版本"
#: assets/models/authbook.py:35
#: assets/models/authbook.py:36
msgid "AuthBook"
msgstr ""
#: assets/models/base.py:31 xpack/plugins/change_auth_plan/models.py:97
#: xpack/plugins/change_auth_plan/models.py:271
#: assets/models/base.py:31 xpack/plugins/change_auth_plan/models.py:96
#: xpack/plugins/change_auth_plan/models.py:270
msgid "SSH private key"
msgstr "ssh密钥"
#: assets/models/base.py:32 xpack/plugins/change_auth_plan/models.py:100
#: xpack/plugins/change_auth_plan/models.py:267
#: assets/models/base.py:32 xpack/plugins/change_auth_plan/models.py:99
#: xpack/plugins/change_auth_plan/models.py:266
msgid "SSH public key"
msgstr "ssh公钥"
#: assets/models/base.py:35 assets/templates/assets/cmd_filter_detail.html:73
#: assets/models/base.py:35 assets/models/gathered_user.py:21
#: assets/templates/assets/cmd_filter_detail.html:73
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:109
#: xpack/plugins/gathered_user/templates/gathered_user/gathered_user_list.html:76
msgid "Date updated"
msgstr "更新日期"
......@@ -965,7 +938,7 @@ msgstr "带宽"
msgid "Contact"
msgstr "联系人"
#: assets/models/cluster.py:22 users/models/user.py:349
#: assets/models/cluster.py:22 users/models/user.py:392
#: users/templates/users/user_detail.html:76
msgid "Phone"
msgstr "手机"
......@@ -991,7 +964,7 @@ msgid "Default"
msgstr "默认"
#: assets/models/cluster.py:36 assets/models/label.py:14
#: users/models/user.py:469
#: users/models/user.py:512
msgid "System"
msgstr "系统"
......@@ -1081,6 +1054,10 @@ msgstr "命令过滤规则"
msgid "Gateway"
msgstr "网关"
#: assets/models/gathered_user.py:32
msgid "GatherUser"
msgstr "收集用户"
#: assets/models/group.py:30
msgid "Asset group"
msgstr "资产组"
......@@ -1110,9 +1087,9 @@ msgstr "默认资产组"
#: terminal/templates/terminal/command_list.html:65
#: terminal/templates/terminal/session_list.html:27
#: terminal/templates/terminal/session_list.html:71 users/forms.py:316
#: users/models/user.py:127 users/models/user.py:457
#: users/serializers/v1.py:108 users/templates/users/user_group_detail.html:78
#: users/templates/users/user_group_list.html:36 users/views/user.py:243
#: users/models/user.py:127 users/models/user.py:143 users/models/user.py:500
#: users/serializers/v1.py:130 users/templates/users/user_group_detail.html:78
#: users/templates/users/user_group_list.html:36 users/views/user.py:250
#: xpack/plugins/orgs/forms.py:26
#: xpack/plugins/orgs/templates/orgs/org_detail.html:113
#: xpack/plugins/orgs/templates/orgs/org_list.html:14
......@@ -1132,11 +1109,11 @@ msgstr "分类"
msgid "New node"
msgstr "新节点"
#: assets/models/node.py:308 perms/api/mixin.py:146
#: assets/models/node.py:308
msgid "ungrouped"
msgstr "未分组"
#: assets/models/node.py:310 perms/api/mixin.py:151
#: assets/models/node.py:310
msgid "empty"
msgstr "空"
......@@ -1171,7 +1148,7 @@ msgstr "手动登录"
#: assets/views/label.py:27 assets/views/label.py:45 assets/views/label.py:73
#: assets/views/system_user.py:29 assets/views/system_user.py:46
#: assets/views/system_user.py:63 assets/views/system_user.py:79
#: templates/_nav.html:19 xpack/plugins/change_auth_plan/models.py:68
#: templates/_nav.html:39 xpack/plugins/change_auth_plan/models.py:67
msgid "Assets"
msgstr "资产管理"
......@@ -1194,11 +1171,45 @@ msgstr "Shell"
msgid "Login mode"
msgstr "登录模式"
#: assets/models/user.py:168 assets/templates/assets/user_asset_list.html:52
#: audits/models.py:20 audits/templates/audits/ftp_log_list.html:52
#: audits/templates/audits/ftp_log_list.html:75
#: perms/forms/asset_permission.py:85 perms/forms/remote_app_permission.py:40
#: perms/models/asset_permission.py:80 perms/models/remote_app_permission.py:16
#: perms/templates/perms/asset_permission_detail.html:140
#: perms/templates/perms/asset_permission_list.html:54
#: perms/templates/perms/asset_permission_list.html:75
#: perms/templates/perms/asset_permission_list.html:127
#: perms/templates/perms/remote_app_permission_detail.html:131
#: templates/_nav.html:45 terminal/backends/command/models.py:14
#: terminal/models.py:156 terminal/templates/terminal/command_list.html:31
#: terminal/templates/terminal/command_list.html:67
#: terminal/templates/terminal/session_list.html:29
#: terminal/templates/terminal/session_list.html:73
#: users/templates/users/_granted_assets.html:27
#: xpack/plugins/orgs/templates/orgs/org_list.html:19
msgid "System user"
msgstr "系统用户"
#: assets/models/utils.py:35
#, python-format
msgid "%(value)s is not an even number"
msgstr "%(value)s is not an even number"
#: assets/models/utils.py:43 assets/tasks/const.py:81
msgid "Unreachable"
msgstr "不可达"
#: assets/models/utils.py:44 assets/tasks/const.py:82
#: assets/templates/assets/asset_list.html:99
msgid "Reachable"
msgstr "可连接"
#: assets/models/utils.py:45 assets/tasks/const.py:83
#: authentication/utils.py:13 xpack/plugins/license/models.py:78
msgid "Unknown"
msgstr "未知"
#: assets/serializers/asset.py:21
msgid "Protocol format should {}/{}"
msgstr "协议格式 {}/{}"
......@@ -1216,7 +1227,7 @@ msgstr "连接"
msgid "Hardware info"
msgstr "硬件信息"
#: assets/serializers/asset.py:91 orgs/mixins/serializers.py:26
#: assets/serializers/asset.py:91 orgs/mixins/serializers.py:27
msgid "Org name"
msgstr "组织名称"
......@@ -1224,8 +1235,8 @@ msgstr "组织名称"
msgid "Backend"
msgstr "后端"
#: assets/serializers/asset_user.py:66 users/forms.py:263
#: users/models/user.py:360 users/templates/users/first_login.html:42
#: assets/serializers/asset_user.py:67 users/forms.py:263
#: users/models/user.py:403 users/templates/users/first_login.html:42
#: users/templates/users/user_password_update.html:49
#: users/templates/users/user_profile.html:69
#: users/templates/users/user_profile_update.html:46
......@@ -1262,88 +1273,93 @@ msgstr "自动登录模式,必须填写用户名"
msgid "Password or private key required"
msgstr "密码或密钥密码需要一个"
#: assets/tasks.py:33
msgid "Asset has been disabled, skipped: {}"
msgstr "资产或许不支持ansible, 跳过: {}"
#: assets/tasks/admin_user_connectivity.py:56
msgid "Test admin user connectivity period: {}"
msgstr "定期测试管理账号可连接性: {}"
#: assets/tasks.py:37
msgid "Asset may not be support ansible, skipped: {}"
msgstr "资产或许不支持ansible, 跳过: {}"
#: assets/tasks/admin_user_connectivity.py:63
msgid "Test admin user connectivity: {}"
msgstr "测试管理行号可连接性: {}"
#: assets/tasks.py:50
msgid "No assets matched, stop task"
msgstr "没有匹配到资产,结束任务"
#: assets/tasks/asset_connectivity.py:21
msgid "Test assets connectivity"
msgstr "测试资产可连接性"
#: assets/tasks.py:60
msgid "No assets matched related system user protocol, stop task"
msgstr "没有匹配到与系统用户协议相关的资产,结束任务"
#: assets/tasks/asset_connectivity.py:75
msgid "Test assets connectivity: {}"
msgstr "测试资产可连接性: {}"
#: assets/tasks.py:86
#: assets/tasks/asset_user_connectivity.py:27
#: assets/tasks/push_system_user.py:130
#: xpack/plugins/change_auth_plan/models.py:521
msgid "The asset {} system platform {} does not support run Ansible tasks"
msgstr "资产 {} 系统平台 {} 不支持运行 Ansible 任务"
#: assets/tasks/asset_user_connectivity.py:74
msgid "Test asset user connectivity: {}"
msgstr "测试资产用户可连接性: {}"
#: assets/tasks/gather_asset_hardware_info.py:44
msgid "Get asset info failed: {}"
msgstr "获取资产信息失败:{}"
#: assets/tasks.py:136
#: assets/tasks/gather_asset_hardware_info.py:94
msgid "Update some assets hardware info"
msgstr "更新资产硬件信息"
#: assets/tasks.py:153
#: assets/tasks/gather_asset_hardware_info.py:111
msgid "Update asset hardware info: {}"
msgstr "更新资产硬件信息: {}"
#: assets/tasks.py:178
msgid "Test assets connectivity"
msgstr "测试资产可连接性"
#: assets/tasks/gather_asset_users.py:95
msgid "Gather assets users"
msgstr "收集资产上的用户"
#: assets/tasks.py:232
msgid "Test assets connectivity: {}"
msgstr "测试资产可连接性: {}"
#: assets/tasks/push_system_user.py:142
msgid ""
"Push system user task skip, auto push not enable or protocol is not ssh or "
"rdp: {}"
msgstr "推送系统用户任务跳过,自动推送没有打开,或协议不是ssh或rdp: {}"
#: assets/tasks.py:274
msgid "Test admin user connectivity period: {}"
msgstr "定期测试管理账号可连接性: {}"
#: assets/tasks/push_system_user.py:149
msgid "For security, do not push user {}"
msgstr "为了安全,禁止推送用户 {}"
#: assets/tasks.py:281
msgid "Test admin user connectivity: {}"
msgstr "测试管理行号可连接性: {}"
#: assets/tasks/push_system_user.py:177 assets/tasks/push_system_user.py:191
msgid "Push system users to assets: {}"
msgstr "推送系统用户到入资产: {}"
#: assets/tasks.py:349
#: assets/tasks/push_system_user.py:183
msgid "Push system users to asset: {} => {}"
msgstr "推送系统用户到入资产: {} => {}"
#: assets/tasks/system_user_connectivity.py:79
msgid "Test system user connectivity: {}"
msgstr "测试系统用户可连接性: {}"
#: assets/tasks.py:356
#: assets/tasks/system_user_connectivity.py:86
msgid "Test system user connectivity: {} => {}"
msgstr "测试系统用户可连接性: {} => {}"
#: assets/tasks.py:369
#: assets/tasks/system_user_connectivity.py:99
msgid "Test system user connectivity period: {}"
msgstr "定期测试系统用户可连接性: {}"
#: assets/tasks.py:487 assets/tasks.py:573
#: xpack/plugins/change_auth_plan/models.py:522
msgid "The asset {} system platform {} does not support run Ansible tasks"
msgstr "资产 {} 系统平台 {} 不支持运行 Ansible 任务"
#: assets/tasks.py:499
msgid ""
"Push system user task skip, auto push not enable or protocol is not ssh or "
"rdp: {}"
msgstr "推送系统用户任务跳过,自动推送没有打开,或协议不是ssh或rdp: {}"
#: assets/tasks.py:506
msgid "For security, do not push user {}"
msgstr "为了安全,禁止推送用户 {}"
#: assets/tasks/utils.py:16
msgid "Asset has been disabled, skipped: {}"
msgstr "资产或许不支持ansible, 跳过: {}"
#: assets/tasks.py:534 assets/tasks.py:548
msgid "Push system users to assets: {}"
msgstr "推送系统用户到入资产: {}"
#: assets/tasks/utils.py:20
msgid "Asset may not be support ansible, skipped: {}"
msgstr "资产或许不支持ansible, 跳过: {}"
#: assets/tasks.py:540
msgid "Push system users to asset: {} => {}"
msgstr "推送系统用户到入资产: {} => {}"
#: assets/tasks/utils.py:33
msgid "No assets matched, stop task"
msgstr "没有匹配到资产,结束任务"
#: assets/tasks.py:620
msgid "Test asset user connectivity: {}"
msgstr "测试资产用户可连接性: {}"
#: assets/tasks/utils.py:43
msgid "No assets matched related system user protocol, stop task"
msgstr "没有匹配到与系统用户协议相关的资产,结束任务"
#: assets/templates/assets/_admin_user_import_modal.html:4
msgid "Import admin user"
......@@ -1385,12 +1401,13 @@ msgid "Import assets"
msgstr "导入资产"
#: assets/templates/assets/_asset_list_modal.html:7 assets/views/asset.py:38
#: templates/_nav.html:22 xpack/plugins/change_auth_plan/views.py:115
#: templates/_nav.html:42 xpack/plugins/change_auth_plan/views.py:115
msgid "Asset list"
msgstr "资产列表"
#: assets/templates/assets/_asset_list_modal.html:33
#: assets/templates/assets/_node_tree.html:40
#: ops/templates/ops/command_execution_create.html:49
#: users/templates/users/_granted_assets.html:7
#: users/templates/users/_granted_assets.html:83
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:66
......@@ -1412,8 +1429,8 @@ msgstr "请输入密码"
#: assets/templates/assets/_asset_user_auth_update_modal.html:68
#: assets/templates/assets/asset_detail.html:306
#: users/templates/users/user_detail.html:311
#: users/templates/users/user_detail.html:338
#: users/templates/users/user_detail.html:313
#: users/templates/users/user_detail.html:340
#: xpack/plugins/interface/views.py:35
msgid "Update successfully!"
msgstr "更新成功"
......@@ -1537,7 +1554,7 @@ msgstr "自动生成密钥"
#: assets/templates/assets/asset_create.html:74
#: assets/templates/assets/gateway_create_update.html:53
#: perms/templates/perms/asset_permission_create_update.html:53
#: perms/templates/perms/remote_app_permission_create_update.html:52
#: perms/templates/perms/remote_app_permission_create_update.html:53
#: terminal/templates/terminal/terminal_update.html:40
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:67
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:48
......@@ -1605,10 +1622,10 @@ msgstr "选择节点"
#: authentication/templates/authentication/_mfa_confirm_modal.html:20
#: settings/templates/settings/terminal_setting.html:168
#: templates/_modal.html:23 terminal/templates/terminal/session_detail.html:108
#: users/templates/users/user_detail.html:392
#: users/templates/users/user_detail.html:418
#: users/templates/users/user_detail.html:441
#: users/templates/users/user_detail.html:486
#: users/templates/users/user_detail.html:394
#: users/templates/users/user_detail.html:420
#: users/templates/users/user_detail.html:443
#: users/templates/users/user_detail.html:488
#: users/templates/users/user_group_create_update.html:32
#: users/templates/users/user_group_list.html:120
#: users/templates/users/user_list.html:256
......@@ -1638,6 +1655,7 @@ msgstr "Jumpserver 使用该用户来 `推送系统用户`、`获取资产硬件
#: audits/templates/audits/login_log_list.html:91
#: users/templates/users/user_group_list.html:10
#: users/templates/users/user_list.html:10
#: xpack/plugins/gathered_user/templates/gathered_user/gathered_user_list.html:59
#: xpack/plugins/vault/templates/vault/vault.html:55
msgid "Export"
msgstr "导出"
......@@ -1721,7 +1739,7 @@ msgstr "创建日期"
#: perms/models/base.py:51
#: perms/templates/perms/asset_permission_create_update.html:55
#: perms/templates/perms/asset_permission_detail.html:120
#: perms/templates/perms/remote_app_permission_create_update.html:54
#: perms/templates/perms/remote_app_permission_create_update.html:55
#: perms/templates/perms/remote_app_permission_detail.html:112
#: terminal/templates/terminal/terminal_list.html:34
#: users/templates/users/_select_user_modal.html:18
......@@ -1805,9 +1823,9 @@ msgstr "显示所有子节点资产"
#: assets/templates/assets/asset_list.html:412
#: assets/templates/assets/system_user_list.html:133
#: users/templates/users/user_detail.html:386
#: users/templates/users/user_detail.html:412
#: users/templates/users/user_detail.html:480
#: users/templates/users/user_detail.html:388
#: users/templates/users/user_detail.html:414
#: users/templates/users/user_detail.html:482
#: users/templates/users/user_group_list.html:114
#: users/templates/users/user_list.html:250
#: xpack/plugins/interface/templates/interface/interface.html:97
......@@ -1821,9 +1839,9 @@ msgstr "删除选择资产"
#: assets/templates/assets/asset_list.html:416
#: assets/templates/assets/system_user_list.html:137
#: settings/templates/settings/terminal_setting.html:166
#: users/templates/users/user_detail.html:390
#: users/templates/users/user_detail.html:416
#: users/templates/users/user_detail.html:484
#: users/templates/users/user_detail.html:392
#: users/templates/users/user_detail.html:418
#: users/templates/users/user_detail.html:486
#: users/templates/users/user_group_create_update.html:31
#: users/templates/users/user_group_list.html:118
#: users/templates/users/user_list.html:254
......@@ -2082,7 +2100,7 @@ msgstr "创建命令过滤器规则"
msgid "Update command filter rule"
msgstr "更新命令过滤器规则"
#: assets/views/domain.py:31 templates/_nav.html:23
#: assets/views/domain.py:31 templates/_nav.html:43
msgid "Domain list"
msgstr "网域列表"
......@@ -2153,7 +2171,7 @@ msgstr "文件名"
#: audits/templates/audits/ftp_log_list.html:79
#: ops/templates/ops/command_execution_list.html:68
#: ops/templates/ops/task_list.html:31
#: users/templates/users/user_detail.html:462
#: users/templates/users/user_detail.html:464
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:14
#: xpack/plugins/cloud/api.py:61
msgid "Success"
......@@ -2161,6 +2179,7 @@ msgstr "成功"
#: audits/models.py:32
#: authentication/templates/authentication/_access_key_modal.html:38
#: xpack/plugins/gathered_user/templates/gathered_user/gathered_user_list.html:48
#: xpack/plugins/vault/templates/vault/vault.html:46
msgid "Create"
msgstr "创建"
......@@ -2214,13 +2233,13 @@ msgstr "Agent"
#: audits/models.py:85 audits/templates/audits/login_log_list.html:62
#: authentication/templates/authentication/_mfa_confirm_modal.html:14
#: users/forms.py:175 users/models/user.py:352
#: users/forms.py:175 users/models/user.py:395
#: users/templates/users/first_login.html:45
msgid "MFA"
msgstr "MFA"
#: audits/models.py:86 audits/templates/audits/login_log_list.html:63
#: xpack/plugins/change_auth_plan/models.py:417
#: xpack/plugins/change_auth_plan/models.py:416
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:15
#: xpack/plugins/cloud/models.py:281
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:69
......@@ -2246,8 +2265,8 @@ msgstr "登录日期"
#: perms/templates/perms/asset_permission_detail.html:86
#: perms/templates/perms/remote_app_permission_detail.html:78
#: terminal/models.py:165 terminal/templates/terminal/session_list.html:34
#: xpack/plugins/change_auth_plan/models.py:250
#: xpack/plugins/change_auth_plan/models.py:420
#: xpack/plugins/change_auth_plan/models.py:249
#: xpack/plugins/change_auth_plan/models.py:419
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:59
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:17
msgid "Date start"
......@@ -2297,47 +2316,46 @@ msgstr "城市"
msgid "Date"
msgstr "日期"
#: audits/views.py:85 audits/views.py:129 audits/views.py:166
#: audits/views.py:211 audits/views.py:243 templates/_nav.html:87
#: templates/_nav_audits.html:22
#: audits/views.py:86 audits/views.py:130 audits/views.py:167
#: audits/views.py:212 audits/views.py:244 templates/_nav.html:126
msgid "Audits"
msgstr "日志审计"
#: audits/views.py:86 templates/_nav.html:91 templates/_nav_audits.html:26
#: audits/views.py:87 templates/_nav.html:130
msgid "FTP log"
msgstr "FTP日志"
#: audits/views.py:130 templates/_nav.html:92 templates/_nav_audits.html:27
#: audits/views.py:131 templates/_nav.html:131
msgid "Operate log"
msgstr "操作日志"
#: audits/views.py:167 templates/_nav.html:93 templates/_nav_audits.html:28
#: audits/views.py:168 templates/_nav.html:132
msgid "Password change log"
msgstr "改密日志"
#: audits/views.py:212 templates/_nav.html:90 templates/_nav_audits.html:25
#: audits/views.py:213 templates/_nav.html:129
msgid "Login log"
msgstr "登录日志"
#: audits/views.py:244
#: audits/views.py:245
msgid "Command execution log"
msgstr "命令执行"
#: authentication/api/auth.py:51 authentication/api/token.py:45
#: authentication/api/auth.py:61 authentication/api/token.py:45
#: authentication/templates/authentication/login.html:52
#: authentication/templates/authentication/new_login.html:77
msgid "Log in frequently and try again later"
msgstr "登录频繁, 稍后重试"
#: authentication/api/auth.py:76
#: authentication/api/auth.py:86
msgid "Please carry seed value and conduct MFA secondary certification"
msgstr "请携带seed值, 进行MFA二次认证"
#: authentication/api/auth.py:156
#: authentication/api/auth.py:176
msgid "Please verify the user name and password first"
msgstr "请先进行用户名和密码验证"
#: authentication/api/auth.py:161
#: authentication/api/auth.py:181
msgid "MFA certification failed"
msgstr "MFA认证失败"
......@@ -2467,14 +2485,14 @@ msgid "Show"
msgstr "显示"
#: authentication/templates/authentication/_access_key_modal.html:66
#: users/models/user.py:287 users/templates/users/user_profile.html:94
#: users/models/user.py:330 users/templates/users/user_profile.html:94
#: users/templates/users/user_profile.html:163
#: users/templates/users/user_profile.html:166
msgid "Disable"
msgstr "禁用"
#: authentication/templates/authentication/_access_key_modal.html:67
#: users/models/user.py:288 users/templates/users/user_profile.html:92
#: users/models/user.py:331 users/templates/users/user_profile.html:92
#: users/templates/users/user_profile.html:170
msgid "Enable"
msgstr "启用"
......@@ -2611,8 +2629,8 @@ msgstr "欢迎回来,请输入用户名和密码登录"
msgid "Please enable cookies and try again."
msgstr "设置你的浏览器支持cookie"
#: authentication/views/login.py:174 users/views/user.py:386
#: users/views/user.py:411
#: authentication/views/login.py:174 users/views/user.py:393
#: users/views/user.py:418
msgid "MFA code invalid, or ntp sync server time"
msgstr "MFA验证码不正确,或者服务器端时间不对"
......@@ -2670,16 +2688,16 @@ msgstr ""
msgid "Encrypt field using Secret Key"
msgstr ""
#: common/mixins/api.py:63
#: common/mixins/api.py:64
#, python-format
msgid "%(name)s was %(action)s successfully"
msgstr "%(name)s %(action)s成功"
#: common/mixins/api.py:64
#: common/mixins/api.py:65
msgid "create"
msgstr "创建"
#: common/mixins/api.py:64
#: common/mixins/api.py:65
msgid "update"
msgstr "更新"
......@@ -2699,11 +2717,11 @@ msgstr "不能包含特殊字符"
msgid "This field must be unique."
msgstr "字段必须唯一"
#: jumpserver/views.py:188 templates/_nav.html:4 templates/_nav_audits.html:4
#: jumpserver/views.py:184 templates/_nav.html:7
msgid "Dashboard"
msgstr "仪表盘"
#: jumpserver/views.py:197
#: jumpserver/views.py:193
msgid ""
"<div>Luna is a separately deployed program, you need to deploy Luna, coco, "
"configure nginx for url distribution,</div> </div>If you see this page, "
......@@ -2800,8 +2818,8 @@ msgstr "完成时间"
#: ops/models/adhoc.py:327 ops/templates/ops/adhoc_history.html:57
#: ops/templates/ops/task_history.html:63 ops/templates/ops/task_list.html:33
#: xpack/plugins/change_auth_plan/models.py:253
#: xpack/plugins/change_auth_plan/models.py:423
#: xpack/plugins/change_auth_plan/models.py:252
#: xpack/plugins/change_auth_plan/models.py:422
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:58
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:16
msgid "Time"
......@@ -2950,39 +2968,39 @@ msgstr "成功资产"
msgid "Task log"
msgstr "任务列表"
#: ops/templates/ops/command_execution_create.html:71
#: ops/templates/ops/command_execution_create.html:90
#: terminal/templates/terminal/session_detail.html:91
#: terminal/templates/terminal/session_detail.html:100
msgid "Go"
msgstr ""
#: ops/templates/ops/command_execution_create.html:197
#: ops/templates/ops/command_execution_create.html:215
msgid "Selected assets"
msgstr "已选择资产"
#: ops/templates/ops/command_execution_create.html:200
#: ops/templates/ops/command_execution_create.html:218
msgid "In total"
msgstr "总共"
#: ops/templates/ops/command_execution_create.html:236
#: ops/templates/ops/command_execution_create.html:254
msgid ""
"Select the left asset, select the running system user, execute command in "
"batch"
msgstr "选择左侧资产, 选择运行的系统用户,批量执行命令"
#: ops/templates/ops/command_execution_create.html:257
#: ops/templates/ops/command_execution_create.html:275
msgid "Unselected assets"
msgstr "没有选中资产"
#: ops/templates/ops/command_execution_create.html:261
#: ops/templates/ops/command_execution_create.html:279
msgid "No input command"
msgstr "没有输入命令"
#: ops/templates/ops/command_execution_create.html:265
#: ops/templates/ops/command_execution_create.html:283
msgid "No system user was selected"
msgstr "没有选择系统用户"
#: ops/templates/ops/command_execution_create.html:310
#: ops/templates/ops/command_execution_create.html:328
msgid "Pending"
msgstr "等待"
......@@ -3044,11 +3062,11 @@ msgstr "更新任务内容: {}"
#: ops/views/adhoc.py:45 ops/views/adhoc.py:71 ops/views/adhoc.py:85
#: ops/views/adhoc.py:99 ops/views/adhoc.py:113 ops/views/adhoc.py:127
#: ops/views/adhoc.py:141 ops/views/command.py:47 ops/views/command.py:77
#: ops/views/adhoc.py:141 ops/views/command.py:48 ops/views/command.py:79
msgid "Ops"
msgstr "作业中心"
#: ops/views/adhoc.py:46 templates/_nav.html:81
#: ops/views/adhoc.py:46 templates/_nav.html:115
msgid "Task list"
msgstr "任务列表"
......@@ -3056,15 +3074,15 @@ msgstr "任务列表"
msgid "Task run history"
msgstr "执行历史"
#: ops/views/command.py:48
#: ops/views/command.py:49
msgid "Command execution list"
msgstr "命令执行列表"
#: ops/views/command.py:78 templates/_nav_user.html:26
#: ops/views/command.py:80 templates/_nav_user.html:26
msgid "Command execution"
msgstr "命令执行"
#: orgs/mixins/models.py:61 orgs/mixins/serializers.py:25 orgs/models.py:29
#: orgs/mixins/models.py:61 orgs/mixins/serializers.py:26 orgs/models.py:30
msgid "Organization"
msgstr "组织"
......@@ -3081,9 +3099,9 @@ msgstr "空"
#: perms/templates/perms/asset_permission_list.html:71
#: perms/templates/perms/asset_permission_list.html:118
#: perms/templates/perms/remote_app_permission_list.html:16
#: templates/_nav.html:14 users/forms.py:286 users/models/group.py:26
#: users/models/user.py:336 users/templates/users/_select_user_modal.html:16
#: users/templates/users/user_detail.html:217
#: templates/_nav.html:21 users/forms.py:286 users/models/group.py:26
#: users/models/user.py:379 users/templates/users/_select_user_modal.html:16
#: users/templates/users/user_detail.html:218
#: users/templates/users/user_list.html:38
#: xpack/plugins/orgs/templates/orgs/org_list.html:15
msgid "User group"
......@@ -3095,7 +3113,7 @@ msgid ""
"downloading files"
msgstr "提示:RDP 协议不支持单独控制上传或下载文件"
#: perms/forms/asset_permission.py:102 perms/forms/remote_app_permission.py:47
#: perms/forms/asset_permission.py:102 perms/forms/remote_app_permission.py:50
msgid "User or group at least one required"
msgstr "用户和用户组至少选一个"
......@@ -3123,19 +3141,19 @@ msgstr "上传下载"
msgid "Actions"
msgstr "动作"
#: perms/models/asset_permission.py:85 templates/_nav.html:44
#: perms/models/asset_permission.py:85 templates/_nav.html:72
msgid "Asset permission"
msgstr "资产授权"
#: perms/models/base.py:53
#: perms/templates/perms/asset_permission_detail.html:90
#: perms/templates/perms/remote_app_permission_detail.html:82
#: users/models/user.py:368 users/templates/users/user_detail.html:107
#: users/models/user.py:411 users/templates/users/user_detail.html:107
#: users/templates/users/user_profile.html:120
msgid "Date expired"
msgstr "失效日期"
#: perms/models/remote_app_permission.py:19
#: perms/models/remote_app_permission.py:20
msgid "RemoteApp permission"
msgstr "远程应用授权"
......@@ -3165,6 +3183,7 @@ msgstr "添加资产"
#: perms/templates/perms/asset_permission_detail.html:157
#: perms/templates/perms/asset_permission_user.html:97
#: perms/templates/perms/asset_permission_user.html:125
#: perms/templates/perms/remote_app_permission_detail.html:148
#: perms/templates/perms/remote_app_permission_remote_app.html:96
#: perms/templates/perms/remote_app_permission_user.html:96
#: perms/templates/perms/remote_app_permission_user.html:124
......@@ -3182,13 +3201,13 @@ msgid "Add node to this permission"
msgstr "添加节点"
#: perms/templates/perms/asset_permission_asset.html:109
#: users/templates/users/user_detail.html:234
#: users/templates/users/user_detail.html:235
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:115
msgid "Join"
msgstr "加入"
#: perms/templates/perms/asset_permission_create_update.html:61
#: perms/templates/perms/remote_app_permission_create_update.html:60
#: perms/templates/perms/remote_app_permission_create_update.html:61
msgid "Validity period"
msgstr "有效期"
......@@ -3217,6 +3236,7 @@ msgid "System user count"
msgstr "系统用户数量"
#: perms/templates/perms/asset_permission_detail.html:148
#: perms/templates/perms/remote_app_permission_detail.html:139
msgid "Select system users"
msgstr "选择系统用户"
......@@ -3286,13 +3306,13 @@ msgstr "添加用户组"
#: perms/views/asset_permission.py:33 perms/views/asset_permission.py:65
#: perms/views/asset_permission.py:82 perms/views/asset_permission.py:99
#: perms/views/asset_permission.py:136 perms/views/asset_permission.py:171
#: perms/views/asset_permission.py:139 perms/views/asset_permission.py:170
#: perms/views/remote_app_permission.py:33
#: perms/views/remote_app_permission.py:49
#: perms/views/remote_app_permission.py:66
#: perms/views/remote_app_permission.py:81
#: perms/views/remote_app_permission.py:108
#: perms/views/remote_app_permission.py:145 templates/_nav.html:41
#: perms/views/remote_app_permission.py:115
#: perms/views/remote_app_permission.py:148 templates/_nav.html:69
#: xpack/plugins/orgs/templates/orgs/org_list.html:21
msgid "Perms"
msgstr "权限管理"
......@@ -3313,11 +3333,11 @@ msgstr "更新资产授权"
msgid "Asset permission detail"
msgstr "资产授权详情"
#: perms/views/asset_permission.py:137
#: perms/views/asset_permission.py:140
msgid "Asset permission user list"
msgstr "资产授权用户列表"
#: perms/views/asset_permission.py:172
#: perms/views/asset_permission.py:171
msgid "Asset permission asset list"
msgstr "资产授权资产列表"
......@@ -3337,11 +3357,11 @@ msgstr "更新远程应用授权规则"
msgid "RemoteApp permission detail"
msgstr "远程应用授权详情"
#: perms/views/remote_app_permission.py:109
#: perms/views/remote_app_permission.py:116
msgid "RemoteApp permission user list"
msgstr "远程应用授权用户列表"
#: perms/views/remote_app_permission.py:146
#: perms/views/remote_app_permission.py:149
msgid "RemoteApp permission RemoteApp list"
msgstr "远程应用授权远程应用列表"
......@@ -3684,7 +3704,7 @@ msgid "Please submit the LDAP configuration before import"
msgstr "请先提交LDAP配置再进行导入"
#: settings/templates/settings/_ldap_list_users_modal.html:32
#: users/models/user.py:332 users/templates/users/user_detail.html:71
#: users/models/user.py:375 users/templates/users/user_detail.html:71
#: users/templates/users/user_profile.html:59
msgid "Email"
msgstr "邮件"
......@@ -3888,7 +3908,7 @@ msgstr "用户来源不是LDAP"
#: settings/views.py:19 settings/views.py:46 settings/views.py:73
#: settings/views.py:103 settings/views.py:131 settings/views.py:144
#: settings/views.py:158 settings/views.py:185 templates/_nav.html:122
#: settings/views.py:158 settings/views.py:185 templates/_nav.html:167
msgid "Settings"
msgstr "系统设置"
......@@ -3917,14 +3937,15 @@ msgstr "文档"
msgid "Commercial support"
msgstr "商业支持"
#: templates/_header_bar.html:70 templates/_nav_user.html:32 users/forms.py:154
#: templates/_header_bar.html:70 templates/_nav.html:30
#: templates/_nav_user.html:32 users/forms.py:154
#: users/templates/users/_user.html:43
#: users/templates/users/first_login.html:39
#: users/templates/users/user_password_update.html:40
#: users/templates/users/user_profile.html:17
#: users/templates/users/user_profile_update.html:37
#: users/templates/users/user_profile_update.html:61
#: users/templates/users/user_pubkey_update.html:37 users/views/user.py:224
#: users/templates/users/user_pubkey_update.html:37 users/views/user.py:231
msgid "Profile"
msgstr "个人信息"
......@@ -4029,72 +4050,70 @@ msgstr ""
"\"%(user_pubkey_update)s\"> 链接 </a> 更新\n"
" "
#: templates/_nav.html:10 users/views/group.py:28 users/views/group.py:45
#: users/views/group.py:63 users/views/group.py:81 users/views/group.py:98
#: users/views/login.py:154 users/views/user.py:60 users/views/user.py:77
#: users/views/user.py:121 users/views/user.py:188 users/views/user.py:210
#: users/views/user.py:263 users/views/user.py:298
#: templates/_nav.html:17 users/views/group.py:28 users/views/group.py:45
#: users/views/group.py:63 users/views/group.py:82 users/views/group.py:99
#: users/views/login.py:154 users/views/user.py:61 users/views/user.py:78
#: users/views/user.py:122 users/views/user.py:189 users/views/user.py:217
#: users/views/user.py:270 users/views/user.py:305
msgid "Users"
msgstr "用户管理"
#: templates/_nav.html:13 users/views/user.py:61
#: templates/_nav.html:20 users/views/user.py:62
msgid "User list"
msgstr "用户列表"
#: templates/_nav.html:27
#: templates/_nav.html:47
msgid "Command filters"
msgstr "命令过滤"
#: templates/_nav.html:55 templates/_nav_audits.html:11
#: terminal/views/command.py:21 terminal/views/session.py:43
#: terminal/views/session.py:54 terminal/views/session.py:78
#: terminal/views/terminal.py:32 terminal/views/terminal.py:48
#: terminal/views/terminal.py:61
#: templates/_nav.html:88 terminal/views/command.py:21
#: terminal/views/session.py:43 terminal/views/session.py:54
#: terminal/views/session.py:78 terminal/views/terminal.py:32
#: terminal/views/terminal.py:48 terminal/views/terminal.py:61
msgid "Sessions"
msgstr "会话管理"
#: templates/_nav.html:58 templates/_nav_audits.html:14
#: templates/_nav.html:91
msgid "Session online"
msgstr "在线会话"
#: templates/_nav.html:59 templates/_nav_audits.html:15
#: terminal/views/session.py:55
#: templates/_nav.html:92 terminal/views/session.py:55
msgid "Session offline"
msgstr "历史会话"
#: templates/_nav.html:60 templates/_nav_audits.html:16
#: templates/_nav.html:93
msgid "Commands"
msgstr "命令记录"
#: templates/_nav.html:63 templates/_nav_user.html:37
#: templates/_nav.html:96 templates/_nav_user.html:37
msgid "Web terminal"
msgstr "Web终端"
#: templates/_nav.html:68 templates/_nav_user.html:42
#: templates/_nav.html:97 templates/_nav_user.html:42
msgid "File manager"
msgstr "文件管理"
#: templates/_nav.html:72
#: templates/_nav.html:101
msgid "Terminal"
msgstr "终端管理"
#: templates/_nav.html:78
#: templates/_nav.html:112
msgid "Job Center"
msgstr "作业中心"
#: templates/_nav.html:82 templates/_nav.html:94 templates/_nav_audits.html:29
#: templates/_nav.html:116 templates/_nav.html:133
msgid "Batch command"
msgstr "批量命令"
#: templates/_nav.html:100
#: templates/_nav.html:143
msgid "XPack"
msgstr ""
#: templates/_nav.html:108 xpack/plugins/cloud/views.py:28
#: templates/_nav.html:151 xpack/plugins/cloud/views.py:28
msgid "Account list"
msgstr "账户列表"
#: templates/_nav.html:109
#: templates/_nav.html:152
msgid "Sync instance"
msgstr "同步实例"
......@@ -4476,11 +4495,11 @@ msgid ""
"You should use your ssh client tools connect terminal: {} <br /> <br />{}"
msgstr "你可以使用ssh客户端工具连接终端"
#: users/api/user.py:187
#: users/api/user.py:173
msgid "Could not reset self otp, use profile reset instead"
msgstr "不能再该页面重置MFA, 请去个人信息页面重置"
#: users/forms.py:33 users/models/user.py:340
#: users/forms.py:33 users/models/user.py:383
#: users/templates/users/_select_user_modal.html:15
#: users/templates/users/user_detail.html:87
#: users/templates/users/user_list.html:37
......@@ -4501,7 +4520,7 @@ msgstr ""
msgid "Paste user id_rsa.pub here."
msgstr "复制用户公钥到这里"
#: users/forms.py:52 users/templates/users/user_detail.html:225
#: users/forms.py:52 users/templates/users/user_detail.html:226
msgid "Join user groups"
msgstr "添加到用户组"
......@@ -4509,11 +4528,11 @@ msgstr "添加到用户组"
msgid "Public key should not be the same as your old one."
msgstr "不能和原来的密钥相同"
#: users/forms.py:91 users/forms.py:252 users/serializers/v1.py:94
#: users/forms.py:91 users/forms.py:252 users/serializers/v1.py:116
msgid "Not a valid ssh public key"
msgstr "ssh密钥不合法"
#: users/forms.py:104 users/views/login.py:114 users/views/user.py:280
#: users/forms.py:104 users/views/login.py:114 users/views/user.py:287
msgid "* Your password does not meet the requirements"
msgstr "* 您的密码不符合要求"
......@@ -4525,7 +4544,7 @@ msgstr "生成重置密码链接,通过邮件发送给用户"
msgid "Set password"
msgstr "设置密码"
#: users/forms.py:133 xpack/plugins/change_auth_plan/models.py:86
#: users/forms.py:133 xpack/plugins/change_auth_plan/models.py:85
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:51
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:69
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:57
......@@ -4599,7 +4618,7 @@ msgstr "选择用户"
msgid "User auth from {}, go there change password"
msgstr "用户认证源来自 {}, 请去相应系统修改密码"
#: users/models/user.py:126 users/models/user.py:465
#: users/models/user.py:126 users/models/user.py:508
msgid "Administrator"
msgstr "管理员"
......@@ -4611,68 +4630,80 @@ msgstr "应用程序"
msgid "Auditor"
msgstr "审计员"
#: users/models/user.py:289 users/templates/users/user_profile.html:90
#: users/models/user.py:139
msgid "Org admin"
msgstr "组织管理员"
#: users/models/user.py:141
msgid "Org auditor"
msgstr "组织审计员"
#: users/models/user.py:332 users/templates/users/user_profile.html:90
msgid "Force enable"
msgstr "强制启用"
#: users/models/user.py:343
#: users/models/user.py:386
msgid "Avatar"
msgstr "头像"
#: users/models/user.py:346 users/templates/users/user_detail.html:82
#: users/models/user.py:389 users/templates/users/user_detail.html:82
msgid "Wechat"
msgstr "微信"
#: users/models/user.py:375 users/templates/users/user_detail.html:103
#: users/models/user.py:418 users/templates/users/user_detail.html:103
#: users/templates/users/user_list.html:39
#: users/templates/users/user_profile.html:102
msgid "Source"
msgstr "用户来源"
#: users/models/user.py:379
#: users/models/user.py:422
msgid "Date password last updated"
msgstr "最后更新密码日期"
#: users/models/user.py:468
#: users/models/user.py:511
msgid "Administrator is the super user of system"
msgstr "Administrator是初始的超级管理员"
#: users/serializers/v1.py:39
#: users/serializers/v1.py:45
msgid "Groups name"
msgstr "用户组名"
#: users/serializers/v1.py:40
#: users/serializers/v1.py:46
msgid "Source name"
msgstr "用户来源名"
#: users/serializers/v1.py:41
#: users/serializers/v1.py:47
msgid "Is first login"
msgstr "首次登录"
#: users/serializers/v1.py:42
#: users/serializers/v1.py:48
msgid "Role name"
msgstr "角色名"
#: users/serializers/v1.py:43
#: users/serializers/v1.py:49
msgid "Is valid"
msgstr "账户是否有效"
#: users/serializers/v1.py:44
#: users/serializers/v1.py:50
msgid "Is expired"
msgstr " 是否过期"
#: users/serializers/v1.py:45
#: users/serializers/v1.py:51
msgid "Avatar url"
msgstr "头像路径"
#: users/serializers/v1.py:54
#: users/serializers/v1.py:72
msgid "Role limit to {}"
msgstr "角色只能为 {}"
#: users/serializers/v1.py:66
#: users/serializers/v1.py:84
msgid "Password does not match security rules"
msgstr "密码不满足安全规则"
#: users/serializers/v1.py:147
msgid "Auditors cannot be join in the group"
msgstr ""
#: users/serializers_v2/user.py:36
msgid "name not unique"
msgstr "名称重复"
......@@ -4723,7 +4754,7 @@ msgid "Import users"
msgstr "导入用户"
#: users/templates/users/_user_update_modal.html:4
#: users/templates/users/user_update.html:4 users/views/user.py:122
#: users/templates/users/user_update.html:4 users/views/user.py:123
msgid "Update user"
msgstr "更新用户"
......@@ -4801,7 +4832,7 @@ msgid "Always young, always with tears in my eyes. Stay foolish Stay hungry"
msgstr "永远年轻,永远热泪盈眶 stay foolish stay hungry"
#: users/templates/users/reset_password.html:46
#: users/templates/users/user_detail.html:377 users/utils.py:84
#: users/templates/users/user_detail.html:379 users/utils.py:84
msgid "Reset password"
msgstr "重置密码"
......@@ -4866,12 +4897,12 @@ msgid "Very strong"
msgstr "很强"
#: users/templates/users/user_create.html:4
#: users/templates/users/user_list.html:28 users/views/user.py:78
#: users/templates/users/user_list.html:28 users/views/user.py:79
msgid "Create user"
msgstr "创建用户"
#: users/templates/users/user_detail.html:19
#: users/templates/users/user_granted_asset.html:18 users/views/user.py:189
#: users/templates/users/user_granted_asset.html:18 users/views/user.py:190
msgid "User detail"
msgstr "用户详情"
......@@ -4918,7 +4949,7 @@ msgid "Send reset ssh key mail"
msgstr "发送重置密钥邮件"
#: users/templates/users/user_detail.html:203
#: users/templates/users/user_detail.html:465
#: users/templates/users/user_detail.html:467
msgid "Unblock user"
msgstr "解除登录限制"
......@@ -4926,52 +4957,52 @@ msgstr "解除登录限制"
msgid "Unblock"
msgstr "解除"
#: users/templates/users/user_detail.html:320
#: users/templates/users/user_detail.html:322
msgid "Goto profile page enable MFA"
msgstr "请去个人信息页面启用自己的MFA"
#: users/templates/users/user_detail.html:376
#: users/templates/users/user_detail.html:378
msgid "An e-mail has been sent to the user`s mailbox."
msgstr "已发送邮件到用户邮箱"
#: users/templates/users/user_detail.html:387
#: users/templates/users/user_detail.html:389
msgid "This will reset the user password and send a reset mail"
msgstr "将失效用户当前密码,并发送重设密码邮件到用户邮箱"
#: users/templates/users/user_detail.html:402
#: users/templates/users/user_detail.html:404
msgid ""
"The reset-ssh-public-key E-mail has been sent successfully. Please inform "
"the user to update his new ssh public key."
msgstr "重设密钥邮件将会发送到用户邮箱"
#: users/templates/users/user_detail.html:403
#: users/templates/users/user_detail.html:405
msgid "Reset SSH public key"
msgstr "重置SSH密钥"
#: users/templates/users/user_detail.html:413
#: users/templates/users/user_detail.html:415
msgid "This will reset the user public key and send a reset mail"
msgstr "将会失效用户当前密钥,并发送重置邮件到用户邮箱"
#: users/templates/users/user_detail.html:431
#: users/templates/users/user_detail.html:433
msgid "Successfully updated the SSH public key."
msgstr "更新ssh密钥成功"
#: users/templates/users/user_detail.html:432
#: users/templates/users/user_detail.html:436
#: users/templates/users/user_detail.html:434
#: users/templates/users/user_detail.html:438
msgid "User SSH public key update"
msgstr "ssh密钥"
#: users/templates/users/user_detail.html:481
#: users/templates/users/user_detail.html:483
msgid "After unlocking the user, the user can log in normally."
msgstr "解除用户登录限制后,此用户即可正常登录"
#: users/templates/users/user_detail.html:495
#: users/templates/users/user_detail.html:497
msgid "Reset user MFA success"
msgstr "重置用户MFA成功"
#: users/templates/users/user_group_detail.html:22
#: users/templates/users/user_group_granted_asset.html:18
#: users/views/group.py:82
#: users/views/group.py:83
msgid "User group detail"
msgstr "用户组详情"
......@@ -5005,24 +5036,24 @@ msgstr "用户组删除失败"
msgid "This will delete the selected users !!!"
msgstr "删除选中用户 !!!"
#: users/templates/users/user_list.html:267
#: users/templates/users/user_list.html:262
msgid "User Deleted."
msgstr "已被删除"
#: users/templates/users/user_list.html:268
#: users/templates/users/user_list.html:272
#: users/templates/users/user_list.html:263
#: users/templates/users/user_list.html:267
msgid "User Delete"
msgstr "删除"
#: users/templates/users/user_list.html:271
#: users/templates/users/user_list.html:266
msgid "User Deleting failed."
msgstr "用户删除失败"
#: users/templates/users/user_list.html:324
#: users/templates/users/user_list.html:327
msgid "User is expired"
msgstr "用户已失效"
#: users/templates/users/user_list.html:327
#: users/templates/users/user_list.html:330
msgid "User is inactive"
msgstr "用户已禁用"
......@@ -5327,7 +5358,7 @@ msgstr ""
msgid "User group list"
msgstr "用户组列表"
#: users/views/group.py:99
#: users/views/group.py:100
msgid "User group granted asset"
msgstr "用户组授权资产"
......@@ -5364,47 +5395,47 @@ msgstr "密码不一致"
msgid "First login"
msgstr "首次登录"
#: users/views/user.py:140
#: users/views/user.py:141
msgid "Bulk update user success"
msgstr "批量更新用户成功"
#: users/views/user.py:168
#: users/views/user.py:169
msgid "Bulk update user"
msgstr "批量更新用户"
#: users/views/user.py:211
#: users/views/user.py:218
msgid "User granted assets"
msgstr "用户授权资产"
#: users/views/user.py:244
#: users/views/user.py:251
msgid "Profile setting"
msgstr "个人信息设置"
#: users/views/user.py:264
#: users/views/user.py:271
msgid "Password update"
msgstr "密码更新"
#: users/views/user.py:299
#: users/views/user.py:306
msgid "Public key update"
msgstr "密钥更新"
#: users/views/user.py:341
#: users/views/user.py:348
msgid "Password invalid"
msgstr "用户名或密码无效"
#: users/views/user.py:441
#: users/views/user.py:448
msgid "MFA enable success"
msgstr "MFA 绑定成功"
#: users/views/user.py:442
#: users/views/user.py:449
msgid "MFA enable success, return login page"
msgstr "MFA 绑定成功,返回到登录页面"
#: users/views/user.py:444
#: users/views/user.py:451
msgid "MFA disable success"
msgstr "MFA 解绑成功"
#: users/views/user.py:445
#: users/views/user.py:452
msgid "MFA disable success, return login page"
msgstr "MFA 解绑成功,返回登录页面"
......@@ -5413,7 +5444,7 @@ msgid "Password length"
msgstr "密码长度"
#: xpack/plugins/change_auth_plan/forms.py:51
#: xpack/plugins/change_auth_plan/models.py:213
#: xpack/plugins/change_auth_plan/models.py:212
msgid "* For security, do not change {} user's password"
msgstr "* 为了安全,禁止更改 {} 用户的密码"
......@@ -5461,8 +5492,8 @@ msgstr ""
"具</a>) <br>注意: 如果同时设置了定期执行和周期执行,优先使用定期执行"
#: xpack/plugins/change_auth_plan/meta.py:9
#: xpack/plugins/change_auth_plan/models.py:114
#: xpack/plugins/change_auth_plan/models.py:257
#: xpack/plugins/change_auth_plan/models.py:113
#: xpack/plugins/change_auth_plan/models.py:256
#: xpack/plugins/change_auth_plan/views.py:33
#: xpack/plugins/change_auth_plan/views.py:50
#: xpack/plugins/change_auth_plan/views.py:72
......@@ -5473,61 +5504,61 @@ msgstr ""
msgid "Change auth plan"
msgstr "改密计划"
#: xpack/plugins/change_auth_plan/models.py:55
#: xpack/plugins/change_auth_plan/models.py:54
msgid "Custom password"
msgstr "自定义密码"
#: xpack/plugins/change_auth_plan/models.py:56
#: xpack/plugins/change_auth_plan/models.py:55
msgid "All assets use the same random password"
msgstr "所有资产使用相同的随机密码"
#: xpack/plugins/change_auth_plan/models.py:57
#: xpack/plugins/change_auth_plan/models.py:56
msgid "All assets use different random password"
msgstr "所有资产使用不同的随机密码"
#: xpack/plugins/change_auth_plan/models.py:76
#: xpack/plugins/change_auth_plan/models.py:145
#: xpack/plugins/change_auth_plan/models.py:75
#: xpack/plugins/change_auth_plan/models.py:144
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:100
#: xpack/plugins/cloud/models.py:165 xpack/plugins/cloud/models.py:219
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:91
msgid "Cycle perform"
msgstr "周期执行"
#: xpack/plugins/change_auth_plan/models.py:81
#: xpack/plugins/change_auth_plan/models.py:143
#: xpack/plugins/change_auth_plan/models.py:80
#: xpack/plugins/change_auth_plan/models.py:142
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:92
#: xpack/plugins/cloud/models.py:170 xpack/plugins/cloud/models.py:217
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:83
msgid "Regularly perform"
msgstr "定期执行"
#: xpack/plugins/change_auth_plan/models.py:90
#: xpack/plugins/change_auth_plan/models.py:89
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:74
msgid "Password rules"
msgstr "密码规则"
#: xpack/plugins/change_auth_plan/models.py:217
#: xpack/plugins/change_auth_plan/models.py:216
msgid "Assets is empty, please add the asset"
msgstr "资产为空,请添加资产"
#: xpack/plugins/change_auth_plan/models.py:261
#: xpack/plugins/change_auth_plan/models.py:260
msgid "Change auth plan snapshot"
msgstr "改密计划快照"
#: xpack/plugins/change_auth_plan/models.py:276
#: xpack/plugins/change_auth_plan/models.py:427
#: xpack/plugins/change_auth_plan/models.py:275
#: xpack/plugins/change_auth_plan/models.py:426
msgid "Change auth plan execution"
msgstr "改密计划执行"
#: xpack/plugins/change_auth_plan/models.py:436
#: xpack/plugins/change_auth_plan/models.py:435
msgid "Change auth plan execution subtask"
msgstr "改密计划执行子任务"
#: xpack/plugins/change_auth_plan/models.py:454
#: xpack/plugins/change_auth_plan/models.py:453
msgid "Authentication failed"
msgstr "认证失败"
#: xpack/plugins/change_auth_plan/models.py:456
#: xpack/plugins/change_auth_plan/models.py:455
msgid "Connection timeout"
msgstr "连接超时"
......@@ -5841,6 +5872,28 @@ msgstr "创建同步实例任务"
msgid "Update sync Instance task"
msgstr "更新同步实例任务"
#: xpack/plugins/gathered_user/meta.py:11
#: xpack/plugins/gathered_user/views.py:22
msgid "Gathered user"
msgstr "收集用户"
#: xpack/plugins/gathered_user/templates/gathered_user/gathered_user_list.html:75
msgid "Present"
msgstr "存在"
#: xpack/plugins/gathered_user/views.py:23
msgid "Gathered user list"
msgstr "收集用户列表"
#: xpack/plugins/gathered_user/views.py:37 xpack/plugins/vault/meta.py:11
#: xpack/plugins/vault/views.py:23 xpack/plugins/vault/views.py:38
msgid "Vault"
msgstr "密码匣子"
#: xpack/plugins/gathered_user/views.py:38 xpack/plugins/vault/views.py:39
msgid "vault create"
msgstr "创建"
#: xpack/plugins/interface/forms.py:17 xpack/plugins/interface/models.py:15
msgid "Title of login page"
msgstr "登录页面标题"
......@@ -6051,11 +6104,6 @@ msgstr "创建组织"
msgid "Update org"
msgstr "更新组织"
#: xpack/plugins/vault/meta.py:11 xpack/plugins/vault/views.py:23
#: xpack/plugins/vault/views.py:38
msgid "Vault"
msgstr "密码匣子"
#: xpack/plugins/vault/templates/vault/_xpack_import_modal.html:4
msgid "Import vault"
msgstr "导入密码"
......@@ -6064,10 +6112,6 @@ msgstr "导入密码"
msgid "vault list"
msgstr "密码匣子"
#: xpack/plugins/vault/views.py:39
msgid "vault create"
msgstr "创建"
#~ msgid "* For security, do not change {}'s password"
#~ msgstr "* 为了安全,禁止更改 {} 的密码"
......
......@@ -6,7 +6,9 @@ import os
from django.conf import settings
from django.utils.timezone import get_current_timezone
from django.db.utils import ProgrammingError, OperationalError
from django_celery_beat.models import PeriodicTask, IntervalSchedule, CrontabSchedule
from django_celery_beat.models import (
PeriodicTask, IntervalSchedule, CrontabSchedule, PeriodicTasks
)
def create_or_update_celery_periodic_tasks(tasks):
......@@ -75,17 +77,20 @@ def create_or_update_celery_periodic_tasks(tasks):
task = PeriodicTask.objects.update_or_create(
defaults=defaults, name=name,
)
PeriodicTasks.update_changed()
return task
def disable_celery_periodic_task(task_name):
from django_celery_beat.models import PeriodicTask
PeriodicTask.objects.filter(name=task_name).update(enabled=False)
PeriodicTasks.update_changed()
def delete_celery_periodic_task(task_name):
from django_celery_beat.models import PeriodicTask
PeriodicTask.objects.filter(name=task_name).delete()
PeriodicTasks.update_changed()
def get_celery_task_log_path(task_id):
......
......@@ -51,7 +51,7 @@ class JMSBaseInventory(BaseInventory):
def make_proxy_command(asset):
gateway = asset.domain.random_gateway()
proxy_command_list = [
"ssh", "-p", str(gateway.port),
"ssh", "-o", "Port={}".format(gateway.port),
"-o", "StrictHostKeyChecking=no",
"{}@{}".format(gateway.username, gateway.ip),
"-W", "%h:%p", "-q",
......
......@@ -2,6 +2,7 @@
import os
import subprocess
import datetime
import time
from django.conf import settings
from celery import shared_task, subtask
......@@ -122,3 +123,22 @@ def hello123():
def hello_callback(result):
print(result)
print("Hello callback")
@shared_task
def add(a, b):
time.sleep(5)
return max(b)
@shared_task
def add_m(x):
from celery import chain
a = range(x)
b = [a[i:i + 10] for i in range(0, len(a), 10)]
s = list()
s.append(add.s(b[0], b[1]))
for i in b[1:]:
s.append(add.s(i))
res = chain(*tuple(s))()
return res
......@@ -3,7 +3,7 @@
from django.shortcuts import get_object_or_404
from rest_framework.viewsets import ModelViewSet
from rest_framework_bulk import BulkModelViewSet
from common.mixins import IDInCacheFilterMixin
from common.mixins import CommonApiMixin
from ..utils import set_to_root_org
from ..models import Organization
......@@ -20,14 +20,16 @@ class RootOrgViewMixin:
return super().dispatch(request, *args, **kwargs)
class OrgModelViewSet(IDInCacheFilterMixin, ModelViewSet):
class OrgModelViewSet(CommonApiMixin, ModelViewSet):
def get_queryset(self):
return super().get_queryset().all()
class OrgBulkModelViewSet(IDInCacheFilterMixin, BulkModelViewSet):
class OrgBulkModelViewSet(CommonApiMixin, BulkModelViewSet):
def get_queryset(self):
queryset = super().get_queryset().all()
if hasattr(self, 'swagger_fake_view'):
return queryset[:1]
if hasattr(self, 'action') and self.action == 'list' and \
hasattr(self, 'serializer_class') and \
hasattr(self.serializer_class, 'setup_eager_loading'):
......
......@@ -11,7 +11,8 @@ from ..utils import get_current_org_id_for_serializer
__all__ = [
"OrgResourceSerializerMixin", "BulkOrgResourceSerializerMixin",
"BulkOrgResourceModelSerializer", "OrgMembershipSerializerMixin"
"BulkOrgResourceModelSerializer", "OrgMembershipSerializerMixin",
"OrgResourceModelSerializerMixin",
]
......@@ -42,6 +43,10 @@ class OrgResourceSerializerMixin(serializers.Serializer):
return fields
class OrgResourceModelSerializerMixin(OrgResourceSerializerMixin, serializers.ModelSerializer):
pass
class BulkOrgResourceSerializerMixin(BulkSerializerMixin, OrgResourceSerializerMixin):
pass
......
......@@ -18,6 +18,8 @@ def get_org_from_request(request):
def set_current_org(org):
if isinstance(org, str):
org = Organization.get_instance(org)
setattr(thread_local, 'current_org_id', org.id)
......
# -*- coding: utf-8 -*-
#
import uuid
from django.db.models import Q
from rest_framework.generics import get_object_or_404
from assets.utils import LabelFilterMixin
from common.permissions import IsValidUser, IsOrgAdminOrAppUser
from common.utils import get_logger
from orgs.utils import set_to_root_org
from ..hands import User, UserGroup, Asset, SystemUser
from .. import serializers
from ..hands import User, UserGroup
logger = get_logger(__name__)
......@@ -54,101 +50,3 @@ class UserGroupPermissionMixin:
return user_group
class GrantAssetsMixin(LabelFilterMixin):
serializer_class = serializers.AssetGrantedSerializer
def get_serializer_queryset(self, queryset):
assets_ids = []
system_users_ids = set()
for asset in queryset:
assets_ids.append(asset["id"])
system_users_ids.update(set(asset["system_users"]))
assets = Asset.objects.filter(id__in=assets_ids).only(
*self.serializer_class.Meta.only_fields
)
assets_map = {asset.id: asset for asset in assets}
system_users = SystemUser.objects.filter(id__in=system_users_ids).only(
*self.serializer_class.system_users_only_fields
)
system_users_map = {s.id: s for s in system_users}
data = []
for item in queryset:
i = item["id"]
asset = assets_map.get(i)
if not asset:
continue
_system_users = item["system_users"]
system_users_granted = []
for sid, action in _system_users.items():
system_user = system_users_map.get(sid)
if not system_user:
continue
if not asset.has_protocol(system_user.protocol):
continue
system_user.actions = action
system_users_granted.append(system_user)
asset.system_users_granted = system_users_granted
data.append(asset)
return data
def get_serializer(self, assets_items=None, many=True):
if assets_items is None:
assets_items = []
assets_items = self.get_serializer_queryset(assets_items)
return super().get_serializer(assets_items, many=many)
def filter_queryset_by_id(self, assets_items):
i = self.request.query_params.get("id")
if not i:
return assets_items
try:
pk = uuid.UUID(i)
except ValueError:
return assets_items
assets_map = {asset['id']: asset for asset in assets_items}
if pk in assets_map:
return [assets_map.get(pk)]
else:
return []
def search_queryset(self, assets_items):
search = self.request.query_params.get("search")
if not search:
return assets_items
assets_map = {asset['id']: asset for asset in assets_items}
assets_ids = set(assets_map.keys())
assets_ids_search = Asset.objects.filter(id__in=assets_ids).filter(
Q(hostname__icontains=search) | Q(ip__icontains=search)
).values_list('id', flat=True)
return [assets_map.get(asset_id) for asset_id in assets_ids_search]
def filter_queryset_by_label(self, assets_items):
labels_id = self.get_filter_labels_ids()
if not labels_id:
return assets_items
assets_map = {asset['id']: asset for asset in assets_items}
assets_matched = Asset.objects.filter(id__in=assets_map.keys())
for label_id in labels_id:
assets_matched = assets_matched.filter(labels=label_id)
assets_ids_matched = assets_matched.values_list('id', flat=True)
return [assets_map.get(asset_id) for asset_id in assets_ids_matched]
def sort_queryset(self, assets_items):
order_by = self.request.query_params.get('order', 'hostname')
if order_by not in ['hostname', '-hostname', 'ip', '-ip']:
order_by = 'hostname'
assets_map = {asset['id']: asset for asset in assets_items}
assets_ids_search = Asset.objects.filter(id__in=assets_map.keys())\
.order_by(order_by)\
.values_list('id', flat=True)
return [assets_map.get(asset_id) for asset_id in assets_ids_search]
def filter_queryset(self, assets_items):
assets_items = self.filter_queryset_by_id(assets_items)
assets_items = self.search_queryset(assets_items)
assets_items = self.filter_queryset_by_label(assets_items)
assets_items = self.sort_queryset(assets_items)
return assets_items
......@@ -2,12 +2,12 @@
#
from ..mixin import UserPermissionMixin
from ...utils import AssetPermissionUtilV2, ParserNode
from ...hands import Node
from ...hands import Node, Asset
from common.tree import TreeNodeSerializer
class UserAssetPermissionMixin(UserPermissionMixin):
util = None
util = AssetPermissionUtilV2(None)
tree = None
def initial(self, *args, **kwargs):
......@@ -41,7 +41,9 @@ class UserNodeTreeMixin:
queryset = self.parse_nodes_to_queryset(queryset)
return queryset
def get_serializer(self, queryset, many=True, **kwargs):
def get_serializer(self, queryset=None, many=True, **kwargs):
if queryset is None:
queryset = Node.objects.none()
queryset = self.get_serializer_queryset(queryset)
queryset.sort()
return super().get_serializer(queryset, many=many, **kwargs)
......@@ -64,7 +66,9 @@ class UserAssetTreeMixin:
_queryset = self.parse_assets_to_queryset(queryset, None)
return _queryset
def get_serializer(self, queryset, many=True, **kwargs):
def get_serializer(self, queryset=None, many=True, **kwargs):
if queryset is None:
queryset = Asset.objects.none()
queryset = self.get_serializer_queryset(queryset)
queryset.sort()
return super().get_serializer(queryset, many=many, **kwargs)
......@@ -126,10 +126,10 @@ class AssetPermissionUtilV2(AssetPermissionUtilCacheMixin):
'comment', 'is_active', 'os', 'org_id'
)
def __init__(self, obj, cache_policy='0'):
def __init__(self, obj=None, cache_policy='0'):
self.object = obj
self.cache_policy = cache_policy
self.obj_id = str(obj.id)
self.obj_id = str(obj.id) if obj else None
self._permissions = None
self._permissions_id = None # 标记_permission的唯一值
self._filter_id = 'None' # 当通过filter更改 permission是标记
......@@ -147,6 +147,8 @@ class AssetPermissionUtilV2(AssetPermissionUtilCacheMixin):
def permissions(self):
if self._permissions:
return self._permissions
if self.object is None:
return AssetPermission.objects.none()
object_cls = self.object.__class__.__name__
func = self.get_permissions_map[object_cls]
permissions = func(self.object)
......
......@@ -97,6 +97,8 @@ class LDAPUserListApi(generics.ListAPIView):
serializer_class = LDAPUserSerializer
def get_queryset(self):
if hasattr(self, 'swagger_fake_view'):
return []
util = LDAPUtil()
try:
users = util.search_user_items()
......
......@@ -153,6 +153,7 @@ function activeNav() {
} else {
$("#" + app).addClass('active');
$('#' + app + ' #' + resource).addClass('active');
$('#' + app + ' #' + resource.replace('-', '_')).addClass('active');
}
}
......
......@@ -171,7 +171,5 @@
<script>
$(document).ready(function () {
var current_org = '{{ CURRENT_ORG.name }}';
console.log(current_org);
})
</script>
\ No newline at end of file
......@@ -58,5 +58,5 @@ class TerminalSerializer(serializers.ModelSerializer):
class TerminalRegistrationSerializer(serializers.Serializer):
name = serializers.CharField(max_length=128)
comment = serializers.CharField(max_length=128)
comment = serializers.CharField(max_length=128, )
service_account = ServiceAccountSerializer(read_only=True)
......@@ -14,7 +14,7 @@ from common.permissions import (
IsOrgAdmin, IsCurrentUserOrReadOnly, IsOrgAdminOrAppUser,
CanUpdateDeleteUser,
)
from common.mixins import IDInCacheFilterMixin
from common.mixins import CommonApiMixin
from common.utils import get_logger
from orgs.utils import current_org
from .. import serializers
......@@ -30,7 +30,7 @@ __all__ = [
]
class UserViewSet(IDInCacheFilterMixin, BulkModelViewSet):
class UserViewSet(CommonApiMixin, BulkModelViewSet):
filter_fields = ('username', 'email', 'name', 'id')
search_fields = filter_fields
queryset = User.objects.exclude(role=User.ROLE_APP)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment