mirror of https://github.com/jumpserver/jumpserver
Merge branch 'dev' of github.com:jumpserver/jumpserver into dev
commit
dbdcdb722d
|
@ -41,40 +41,46 @@ class AssetViewSet(IDInFilterMixin, LabelFilter, BulkModelViewSet):
|
|||
pagination_class = LimitOffsetPagination
|
||||
permission_classes = (IsOrgAdminOrAppUser,)
|
||||
|
||||
def filter_node(self):
|
||||
def filter_node(self, queryset):
|
||||
node_id = self.request.query_params.get("node_id")
|
||||
if not node_id:
|
||||
return
|
||||
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_root():
|
||||
if show_current_asset:
|
||||
self.queryset = self.queryset.filter(
|
||||
Q(nodes=node_id) | Q(nodes__isnull=True)
|
||||
)
|
||||
return
|
||||
if show_current_asset:
|
||||
self.queryset = self.queryset.filter(nodes=node)
|
||||
if node.is_root() and show_current_asset:
|
||||
queryset = queryset.filter(
|
||||
Q(nodes=node_id) | Q(nodes__isnull=True)
|
||||
)
|
||||
elif node.is_root() and not show_current_asset:
|
||||
pass
|
||||
elif not node.is_root() and show_current_asset:
|
||||
queryset = queryset.filter(nodes=node)
|
||||
else:
|
||||
self.queryset = self.queryset.filter(
|
||||
queryset = queryset.filter(
|
||||
nodes__key__regex='^{}(:[0-9]+)*$'.format(node.key),
|
||||
)
|
||||
return queryset
|
||||
|
||||
def filter_admin_user_id(self):
|
||||
def filter_admin_user_id(self, queryset):
|
||||
admin_user_id = self.request.query_params.get('admin_user_id')
|
||||
if admin_user_id:
|
||||
admin_user = get_object_or_404(AdminUser, id=admin_user_id)
|
||||
self.queryset = self.queryset.filter(admin_user=admin_user)
|
||||
if not admin_user_id:
|
||||
return queryset
|
||||
admin_user = get_object_or_404(AdminUser, id=admin_user_id)
|
||||
queryset = queryset.filter(admin_user=admin_user)
|
||||
return queryset
|
||||
|
||||
def filter_queryset(self, queryset):
|
||||
queryset = super().filter_queryset(queryset)
|
||||
queryset = self.filter_node(queryset)
|
||||
queryset = self.filter_admin_user_id(queryset)
|
||||
return queryset
|
||||
|
||||
def get_queryset(self):
|
||||
self.queryset = super().get_queryset()\
|
||||
.prefetch_related('labels', 'nodes')\
|
||||
.select_related('admin_user')
|
||||
self.filter_admin_user_id()
|
||||
self.filter_node()
|
||||
return self.queryset.distinct()
|
||||
queryset = super().get_queryset().distinct()
|
||||
queryset = self.get_serializer_class().setup_eager_loading(queryset)
|
||||
return queryset
|
||||
|
||||
|
||||
class AssetListUpdateApi(IDInFilterMixin, ListBulkCreateUpdateDestroyAPIView):
|
||||
|
|
|
@ -17,13 +17,13 @@ from rest_framework import generics, mixins, viewsets
|
|||
from rest_framework.serializers import ValidationError
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework.response import Response
|
||||
from rest_framework_bulk import BulkModelViewSet
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.shortcuts import get_object_or_404
|
||||
|
||||
from common.utils import get_logger, get_object_or_none
|
||||
from common.tree import TreeNodeSerializer
|
||||
from ..hands import IsOrgAdmin
|
||||
from ..models import Node, Asset
|
||||
from ..models import Node
|
||||
from ..tasks import update_assets_hardware_info_util, test_asset_connectability_util
|
||||
from .. import serializers
|
||||
|
||||
|
@ -33,7 +33,8 @@ __all__ = [
|
|||
'NodeViewSet', 'NodeChildrenApi', 'NodeAssetsApi',
|
||||
'NodeAddAssetsApi', 'NodeRemoveAssetsApi', 'NodeReplaceAssetsApi',
|
||||
'NodeAddChildrenApi', 'RefreshNodeHardwareInfoApi',
|
||||
'TestNodeConnectiveApi'
|
||||
'TestNodeConnectiveApi', 'NodeListAsTreeApi',
|
||||
'NodeChildrenAsTreeApi',
|
||||
]
|
||||
|
||||
|
||||
|
@ -42,22 +43,89 @@ class NodeViewSet(viewsets.ModelViewSet):
|
|||
permission_classes = (IsOrgAdmin,)
|
||||
serializer_class = serializers.NodeSerializer
|
||||
|
||||
def perform_create(self, serializer):
|
||||
child_key = Node.root().get_next_child_key()
|
||||
serializer.validated_data["key"] = child_key
|
||||
serializer.save()
|
||||
|
||||
def update(self, request, *args, **kwargs):
|
||||
node = self.get_object()
|
||||
if node.is_root():
|
||||
node_value = node.value
|
||||
post_value = request.data.get('value')
|
||||
if node_value != post_value:
|
||||
return Response(
|
||||
{"msg": _("You can't update the root node name")},
|
||||
status=400
|
||||
)
|
||||
return super().update(request, *args, **kwargs)
|
||||
class NodeListAsTreeApi(generics.ListAPIView):
|
||||
"""
|
||||
获取节点列表树
|
||||
[
|
||||
{
|
||||
"id": "",
|
||||
"name": "",
|
||||
"pId": "",
|
||||
"meta": ""
|
||||
}
|
||||
]
|
||||
"""
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
serializer_class = TreeNodeSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = [node.as_tree_node() for node in Node.objects.all()]
|
||||
return queryset
|
||||
|
||||
def filter_queryset(self, queryset):
|
||||
if self.request.query_params.get('refresh', '0') == '1':
|
||||
queryset = self.refresh_nodes(queryset)
|
||||
return queryset
|
||||
|
||||
@staticmethod
|
||||
def refresh_nodes(queryset):
|
||||
Node.expire_nodes_assets_amount()
|
||||
Node.expire_nodes_full_value()
|
||||
return queryset
|
||||
|
||||
|
||||
class NodeChildrenAsTreeApi(generics.ListAPIView):
|
||||
"""
|
||||
节点子节点作为树返回,
|
||||
[
|
||||
{
|
||||
"id": "",
|
||||
"name": "",
|
||||
"pId": "",
|
||||
"meta": ""
|
||||
}
|
||||
]
|
||||
|
||||
"""
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
serializer_class = TreeNodeSerializer
|
||||
node = None
|
||||
is_root = False
|
||||
|
||||
def get_queryset(self):
|
||||
node_key = self.request.query_params.get('key')
|
||||
if node_key:
|
||||
self.node = Node.objects.get(key=node_key)
|
||||
queryset = self.node.get_children(with_self=False)
|
||||
else:
|
||||
self.is_root = True
|
||||
self.node = Node.root()
|
||||
queryset = list(self.node.get_children(with_self=True))
|
||||
nodes_invalid = Node.objects.exclude(key__startswith=self.node.key)
|
||||
queryset.extend(list(nodes_invalid))
|
||||
queryset = [node.as_tree_node() for node in queryset]
|
||||
return queryset
|
||||
|
||||
def filter_assets(self, queryset):
|
||||
include_assets = self.request.query_params.get('assets', '0') == '1'
|
||||
if not include_assets:
|
||||
return queryset
|
||||
assets = self.node.get_assets()
|
||||
for asset in assets:
|
||||
queryset.append(asset.as_tree_node(self.node))
|
||||
return queryset
|
||||
|
||||
def filter_queryset(self, queryset):
|
||||
queryset = self.filter_assets(queryset)
|
||||
queryset = self.filter_refresh_nodes(queryset)
|
||||
return queryset
|
||||
|
||||
def filter_refresh_nodes(self, queryset):
|
||||
if self.request.query_params.get('refresh', '0') == '1':
|
||||
Node.expire_nodes_assets_amount()
|
||||
Node.expire_nodes_full_value()
|
||||
return queryset
|
||||
|
||||
|
||||
class NodeChildrenApi(mixins.ListModelMixin, generics.CreateAPIView):
|
||||
|
@ -66,19 +134,10 @@ class NodeChildrenApi(mixins.ListModelMixin, generics.CreateAPIView):
|
|||
serializer_class = serializers.NodeSerializer
|
||||
instance = None
|
||||
|
||||
def counter(self):
|
||||
values = [
|
||||
child.value[child.value.rfind(' '):]
|
||||
for child in self.get_object().get_children()
|
||||
if child.value.startswith("新节点 ")
|
||||
]
|
||||
values = [int(value) for value in values if value.strip().isdigit()]
|
||||
count = max(values)+1 if values else 1
|
||||
return count
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
instance = self.get_object()
|
||||
if not request.data.get("value"):
|
||||
request.data["value"] = _("New node {}").format(self.counter())
|
||||
request.data["value"] = instance.get_next_child_preset_name()
|
||||
return super().post(request, *args, **kwargs)
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
|
@ -90,10 +149,7 @@ class NodeChildrenApi(mixins.ListModelMixin, generics.CreateAPIView):
|
|||
'The same level node name cannot be the same'
|
||||
)
|
||||
node = instance.create_child(value=value)
|
||||
return Response(
|
||||
{"id": node.id, "key": node.key, "value": node.value},
|
||||
status=201,
|
||||
)
|
||||
return Response(self.serializer_class(instance=node).data, status=201)
|
||||
|
||||
def get_object(self):
|
||||
pk = self.kwargs.get('pk') or self.request.query_params.get('id')
|
||||
|
@ -106,7 +162,6 @@ class NodeChildrenApi(mixins.ListModelMixin, generics.CreateAPIView):
|
|||
def get_queryset(self):
|
||||
queryset = []
|
||||
query_all = self.request.query_params.get("all")
|
||||
query_assets = self.request.query_params.get('assets')
|
||||
node = self.get_object()
|
||||
|
||||
if node is None:
|
||||
|
@ -119,23 +174,8 @@ class NodeChildrenApi(mixins.ListModelMixin, generics.CreateAPIView):
|
|||
else:
|
||||
children = node.get_children()
|
||||
queryset.extend(list(children))
|
||||
|
||||
if query_assets:
|
||||
assets = node.get_assets()
|
||||
for asset in assets:
|
||||
node_fake = Node()
|
||||
node_fake.assets__count = 0
|
||||
node_fake.id = asset.id
|
||||
node_fake.is_node = False
|
||||
node_fake.key = node.key + ':0'
|
||||
node_fake.value = asset.hostname
|
||||
queryset.append(node_fake)
|
||||
queryset = sorted(queryset, key=lambda x: x.is_node, reverse=True)
|
||||
return queryset
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
return super().list(request, *args, **kwargs)
|
||||
|
||||
|
||||
class NodeAssetsApi(generics.ListAPIView):
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
|
|
|
@ -255,6 +255,36 @@ class Asset(OrgModelMixin):
|
|||
})
|
||||
return data
|
||||
|
||||
def as_tree_node(self, parent_node):
|
||||
from common.tree import TreeNode
|
||||
icon_skin = 'file'
|
||||
if self.platform.lower() == 'windows':
|
||||
icon_skin = 'windows'
|
||||
elif self.platform.lower() == 'linux':
|
||||
icon_skin = 'linux'
|
||||
data = {
|
||||
'id': str(self.id),
|
||||
'name': self.hostname,
|
||||
'title': self.ip,
|
||||
'pId': parent_node.key,
|
||||
'isParent': False,
|
||||
'open': False,
|
||||
'iconSkin': icon_skin,
|
||||
'meta': {
|
||||
'type': 'asset',
|
||||
'asset': {
|
||||
'id': self.id,
|
||||
'hostname': self.hostname,
|
||||
'ip': self.ip,
|
||||
'port': self.port,
|
||||
'platform': self.platform,
|
||||
'protocol': self.protocol,
|
||||
}
|
||||
}
|
||||
}
|
||||
tree_node = TreeNode(**data)
|
||||
return tree_node
|
||||
|
||||
class Meta:
|
||||
unique_together = [('org_id', 'hostname')]
|
||||
verbose_name = _("Asset")
|
||||
|
|
|
@ -5,6 +5,7 @@ import uuid
|
|||
from django.db import models, transaction
|
||||
from django.db.models import Q
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import ugettext
|
||||
from django.core.cache import cache
|
||||
|
||||
from orgs.mixins import OrgModelMixin
|
||||
|
@ -103,6 +104,15 @@ class Node(OrgModelMixin):
|
|||
key = self._full_value_cache_key.format(self.key)
|
||||
cache.delete_pattern(key+'*')
|
||||
|
||||
@classmethod
|
||||
def expire_nodes_full_value(cls, nodes=None):
|
||||
if nodes:
|
||||
for node in nodes:
|
||||
node.expire_full_value()
|
||||
return
|
||||
key = cls._full_value_cache_key.format('*')
|
||||
cache.delete_pattern(key+'*')
|
||||
|
||||
@property
|
||||
def level(self):
|
||||
return len(self.key.split(':'))
|
||||
|
@ -113,6 +123,17 @@ class Node(OrgModelMixin):
|
|||
self.save()
|
||||
return "{}:{}".format(self.key, mark)
|
||||
|
||||
def get_next_child_preset_name(self):
|
||||
name = ugettext("New node")
|
||||
values = [
|
||||
child.value[child.value.rfind(' '):]
|
||||
for child in self.get_children()
|
||||
if child.value.startswith(name)
|
||||
]
|
||||
values = [int(value) for value in values if value.strip().isdigit()]
|
||||
count = max(values) + 1 if values else 1
|
||||
return '{} {}'.format(name, count)
|
||||
|
||||
def create_child(self, value):
|
||||
with transaction.atomic():
|
||||
child_key = self.get_next_child_key()
|
||||
|
@ -162,7 +183,7 @@ class Node(OrgModelMixin):
|
|||
pattern = r'^{0}$|^{0}:'.format(self.key)
|
||||
args = []
|
||||
kwargs = {}
|
||||
if self.is_default_node():
|
||||
if self.is_root():
|
||||
args.append(Q(nodes__key__regex=pattern) | Q(nodes=None))
|
||||
else:
|
||||
kwargs['nodes__key__regex'] = pattern
|
||||
|
@ -256,6 +277,26 @@ class Node(OrgModelMixin):
|
|||
defaults = {'value': 'Default'}
|
||||
return cls.objects.get_or_create(defaults=defaults, key='1')
|
||||
|
||||
def as_tree_node(self):
|
||||
from common.tree import TreeNode
|
||||
from ..serializers import NodeSerializer
|
||||
name = '{} ({})'.format(self.value, self.assets_amount)
|
||||
node_serializer = NodeSerializer(instance=self)
|
||||
data = {
|
||||
'id': self.key,
|
||||
'name': name,
|
||||
'title': name,
|
||||
'pId': self.parent_key,
|
||||
'isParent': True,
|
||||
'open': self.is_root(),
|
||||
'meta': {
|
||||
'node': node_serializer.data,
|
||||
'type': 'node'
|
||||
}
|
||||
}
|
||||
tree_node = TreeNode(**data)
|
||||
return tree_node
|
||||
|
||||
@classmethod
|
||||
def generate_fake(cls, count=100):
|
||||
import random
|
||||
|
|
|
@ -9,6 +9,7 @@ from .system_user import AssetSystemUserSerializer
|
|||
|
||||
__all__ = [
|
||||
'AssetSerializer', 'AssetGrantedSerializer', 'MyAssetGrantedSerializer',
|
||||
'AssetAsNodeSerializer',
|
||||
]
|
||||
|
||||
|
||||
|
@ -22,6 +23,13 @@ class AssetSerializer(BulkSerializerMixin, serializers.ModelSerializer):
|
|||
fields = '__all__'
|
||||
validators = []
|
||||
|
||||
@classmethod
|
||||
def setup_eager_loading(cls, queryset):
|
||||
""" Perform necessary eager loading of data. """
|
||||
queryset = queryset.prefetch_related('labels', 'nodes')\
|
||||
.select_related('admin_user')
|
||||
return queryset
|
||||
|
||||
def get_field_names(self, declared_fields, info):
|
||||
fields = super().get_field_names(declared_fields, info)
|
||||
fields.extend([
|
||||
|
@ -30,6 +38,12 @@ class AssetSerializer(BulkSerializerMixin, serializers.ModelSerializer):
|
|||
return fields
|
||||
|
||||
|
||||
class AssetAsNodeSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Asset
|
||||
fields = ['id', 'hostname', 'ip', 'port', 'platform', 'protocol']
|
||||
|
||||
|
||||
class AssetGrantedSerializer(serializers.ModelSerializer):
|
||||
"""
|
||||
被授权资产的数据结构
|
||||
|
|
|
@ -8,76 +8,33 @@ from .asset import AssetGrantedSerializer
|
|||
|
||||
|
||||
__all__ = [
|
||||
'NodeSerializer', "NodeGrantedSerializer", "NodeAddChildrenSerializer",
|
||||
'NodeSerializer', "NodeAddChildrenSerializer",
|
||||
"NodeAssetsSerializer",
|
||||
]
|
||||
|
||||
|
||||
class NodeGrantedSerializer(BulkSerializerMixin, serializers.ModelSerializer):
|
||||
"""
|
||||
授权资产组
|
||||
"""
|
||||
assets_granted = AssetGrantedSerializer(many=True, read_only=True)
|
||||
assets_amount = serializers.SerializerMethodField()
|
||||
parent = serializers.SerializerMethodField()
|
||||
name = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = Node
|
||||
fields = [
|
||||
'id', 'key', 'name', 'value', 'parent',
|
||||
'assets_granted', 'assets_amount', 'org_id',
|
||||
]
|
||||
|
||||
@staticmethod
|
||||
def get_assets_amount(obj):
|
||||
return len(obj.assets_granted)
|
||||
|
||||
@staticmethod
|
||||
def get_name(obj):
|
||||
return obj.name
|
||||
|
||||
@staticmethod
|
||||
def get_parent(obj):
|
||||
return obj.parent.id
|
||||
|
||||
|
||||
class NodeSerializer(serializers.ModelSerializer):
|
||||
assets_amount = serializers.IntegerField()
|
||||
tree_id = serializers.SerializerMethodField()
|
||||
tree_parent = serializers.SerializerMethodField()
|
||||
assets_amount = serializers.IntegerField(read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = Node
|
||||
fields = [
|
||||
'id', 'key', 'value', 'assets_amount',
|
||||
'is_node', 'org_id', 'tree_id', 'tree_parent',
|
||||
'id', 'key', 'value', 'assets_amount', 'org_id',
|
||||
]
|
||||
read_only_fields = [
|
||||
'id', 'key', 'assets_amount', 'is_node',
|
||||
'org_id',
|
||||
'id', 'key', 'assets_amount', 'org_id',
|
||||
]
|
||||
list_serializer_class = BulkListSerializer
|
||||
|
||||
def validate(self, data):
|
||||
value = data.get('value')
|
||||
def validate_value(self, data):
|
||||
instance = self.instance if self.instance else Node.root()
|
||||
children = instance.parent.get_children().exclude(key=instance.key)
|
||||
values = [child.value for child in children]
|
||||
if value in values:
|
||||
if data in values:
|
||||
raise serializers.ValidationError(
|
||||
'The same level node name cannot be the same'
|
||||
)
|
||||
return data
|
||||
|
||||
@staticmethod
|
||||
def get_tree_id(obj):
|
||||
return obj.key
|
||||
|
||||
@staticmethod
|
||||
def get_tree_parent(obj):
|
||||
return obj.parent_key
|
||||
|
||||
|
||||
class NodeAssetsSerializer(serializers.ModelSerializer):
|
||||
assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all())
|
||||
|
@ -89,3 +46,4 @@ class NodeAssetsSerializer(serializers.ModelSerializer):
|
|||
|
||||
class NodeAddChildrenSerializer(serializers.Serializer):
|
||||
nodes = serializers.ListField()
|
||||
|
||||
|
|
|
@ -136,6 +136,7 @@
|
|||
<li class="divider"></li>
|
||||
<li id="show_current_asset" class="btn-show-current-asset" style="display: none;" tabindex="-1"><a><i class="fa fa-hand-o-up"></i> {% trans 'Display only current node assets' %}</a></li>
|
||||
<li id="show_all_asset" class="btn-show-all-asset" style="display: none;" tabindex="-1"><a><i class="fa fa-th"></i> {% trans 'Displays all child node assets' %}</a></li>
|
||||
<li id="fresh_tree" class="btn-refresh-tree" tabindex="-1"><a><i class="fa fa-refresh"></i> {% trans 'Refresh' %}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
@ -147,6 +148,8 @@
|
|||
<script>
|
||||
var zTree, rMenu, asset_table, show = 0;
|
||||
var update_node_action = "";
|
||||
var current_node_id = null;
|
||||
var current_node = null;
|
||||
function initTable() {
|
||||
var options = {
|
||||
ele: $('#asset_list_table'),
|
||||
|
@ -191,18 +194,20 @@ function addTreeNode() {
|
|||
if (!parentNode){
|
||||
return
|
||||
}
|
||||
var url = "{% url 'api-assets:node-children' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", parentNode.node_id );
|
||||
var url = "{% url 'api-assets:node-children' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", parentNode.meta.node.id);
|
||||
$.post(url, {}, function (data, status){
|
||||
if (status === "success") {
|
||||
var newNode = {
|
||||
id: data["key"],
|
||||
name: data["value"],
|
||||
node_id: data["id"],
|
||||
pId: parentNode.id
|
||||
pId: parentNode.id,
|
||||
meta: {
|
||||
"node": data
|
||||
}
|
||||
};
|
||||
newNode.checked = zTree.getSelectedNodes()[0].checked;
|
||||
zTree.addNodes(parentNode, 0, newNode);
|
||||
var node = zTree.getNodeByParam('id', newNode.node_id, parentNode);
|
||||
var node = zTree.getNodeByParam('id', newNode.id, parentNode);
|
||||
zTree.editName(node);
|
||||
} else {
|
||||
alert("{% trans 'Create node failed' %}")
|
||||
|
@ -218,10 +223,10 @@ function removeTreeNode() {
|
|||
}
|
||||
if (current_node.children && current_node.children.length > 0) {
|
||||
toastr.error("{% trans 'Have child node, cancel' %}");
|
||||
} else if (current_node.assets_amount !== 0) {
|
||||
} else if (current_node.meta.node.assets_amount !== 0) {
|
||||
toastr.error("{% trans 'Have assets, cancel' %}");
|
||||
} else {
|
||||
var url = "{% url 'api-assets:node-detail' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", current_node.node_id );
|
||||
var url = "{% url 'api-assets:node-detail' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", current_node_id);
|
||||
$.ajax({
|
||||
url: url,
|
||||
method: "DELETE",
|
||||
|
@ -238,8 +243,8 @@ function editTreeNode() {
|
|||
if (!current_node){
|
||||
return
|
||||
}
|
||||
if (current_node.value) {
|
||||
current_node.name = current_node.value;
|
||||
if (current_node) {
|
||||
current_node.name = current_node.meta.node.value;
|
||||
}
|
||||
zTree.editName(current_node);
|
||||
}
|
||||
|
@ -281,7 +286,7 @@ function onBodyMouseDown(event){
|
|||
|
||||
|
||||
function onRename(event, treeId, treeNode, isCancel){
|
||||
var url = "{% url 'api-assets:node-detail' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", treeNode.node_id);
|
||||
var url = "{% url 'api-assets:node-detail' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", current_node_id);
|
||||
var data = {"value": treeNode.name};
|
||||
if (isCancel){
|
||||
return
|
||||
|
@ -291,13 +296,20 @@ function onRename(event, treeId, treeNode, isCancel){
|
|||
body: JSON.stringify(data),
|
||||
method: "PATCH",
|
||||
success_message: "{% trans 'Rename success' %}",
|
||||
fail_message: "{% trans 'Rename failed, do not change the root node name' %}"
|
||||
fail_message: "{% trans 'Rename failed, do not change the root node name' %}",
|
||||
success: function () {
|
||||
treeNode.name = treeNode.name + ' (' + treeNode.meta.node.assets_amount + ')'
|
||||
zTree.updateNode(treeNode);
|
||||
console.log("Success: " + treeNode.name)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function onSelected(event, treeNode) {
|
||||
current_node = treeNode;
|
||||
current_node_id = treeNode.meta.node.id;
|
||||
var url = asset_table.ajax.url();
|
||||
url = setUrlParam(url, "node_id", treeNode.node_id);
|
||||
url = setUrlParam(url, "node_id", current_node_id);
|
||||
url = setUrlParam(url, "show_current_asset", getCookie('show_current_asset'));
|
||||
setCookie('node_selected', treeNode.node_id);
|
||||
asset_table.ajax.url(url);
|
||||
|
@ -361,6 +373,11 @@ function initTree() {
|
|||
if (zTree) {
|
||||
return
|
||||
}
|
||||
var url = '{% url 'api-assets:node-children-tree' %}?assets=0&all=';
|
||||
var showCurrentAsset = getCookie('show_current_asset');
|
||||
if (!showCurrentAsset) {
|
||||
url += '1'
|
||||
}
|
||||
var setting = {
|
||||
view: {
|
||||
dblClickExpand: false,
|
||||
|
@ -371,6 +388,12 @@ function initTree() {
|
|||
enable: true
|
||||
}
|
||||
},
|
||||
async: {
|
||||
enable: true,
|
||||
url: url,
|
||||
autoParam: ["id=key", "name=n", "level=lv"],
|
||||
type: 'get'
|
||||
},
|
||||
edit: {
|
||||
enable: true,
|
||||
showRemoveBtn: false,
|
||||
|
@ -393,27 +416,8 @@ function initTree() {
|
|||
};
|
||||
|
||||
var zNodes = [];
|
||||
console.log("Get assets")
|
||||
$.get("{% url 'api-assets:node-list' %}", function(data, status){
|
||||
$.each(data, function (index, value) {
|
||||
value["node_id"] = value["id"];
|
||||
value["id"] = value["tree_id"];
|
||||
if (value["tree_id"] !== value["tree_parent"]){
|
||||
value["pId"] = value["tree_parent"];
|
||||
} else {
|
||||
value["isParent"] = true;
|
||||
}
|
||||
value["name"] = value["value"] + ' (' + value['assets_amount'] + ')';
|
||||
value['value'] = value['value'];
|
||||
});
|
||||
zNodes = data;
|
||||
$.fn.zTree.init($("#assetTree"), setting, zNodes);
|
||||
zTree = $.fn.zTree.getZTreeObj("assetTree");
|
||||
var root = zTree.getNodes()[0];
|
||||
zTree.expandNode(root);
|
||||
rMenu = $("#rMenu");
|
||||
selectQueryNode();
|
||||
});
|
||||
zTree = $.fn.zTree.init($("#assetTree"), setting, zNodes);
|
||||
rMenu = $("#rMenu");
|
||||
}
|
||||
|
||||
function toggle() {
|
||||
|
@ -450,20 +454,15 @@ $(document).ready(function(){
|
|||
.on('click', '.btn_export', function () {
|
||||
var $data_table = $('#asset_list_table').DataTable();
|
||||
var rows = $data_table.rows('.selected').data();
|
||||
var nodes = zTree.getSelectedNodes();
|
||||
var current_node;
|
||||
if (nodes && nodes.length === 1) {
|
||||
current_node = nodes[0];
|
||||
}
|
||||
|
||||
var assets = [];
|
||||
$.each(rows, function (index, obj) {
|
||||
assets.push(obj.id)
|
||||
});
|
||||
var _node_id = current_node ? current_node.node_id : null;
|
||||
$.ajax({
|
||||
url: "{% url "assets:asset-export" %}",
|
||||
method: 'POST',
|
||||
data: JSON.stringify({assets_id: assets, node_id: _node_id}),
|
||||
data: JSON.stringify({assets_id: assets, node_id: current_node_id}),
|
||||
dataType: "json",
|
||||
success: function (data, textStatus) {
|
||||
window.open(data.redirect)
|
||||
|
@ -476,12 +475,8 @@ $(document).ready(function(){
|
|||
.on('click', '#btn_asset_import', function () {
|
||||
var $form = $('#fm_asset_import');
|
||||
var action = $form.attr("action");
|
||||
var nodes = zTree.getSelectedNodes();
|
||||
var current_node;
|
||||
if (nodes && nodes.length ===1 ){
|
||||
current_node = nodes[0];
|
||||
action = setUrlParam(action, 'node_id', current_node.node_id);
|
||||
{#action += "?node_id=" + current_node.node_id;#}
|
||||
if (current_node_id){
|
||||
action = setUrlParam(action, 'node_id', current_node_id);
|
||||
$form.attr("action", action)
|
||||
}
|
||||
$form.find('.help-block').remove();
|
||||
|
@ -503,25 +498,14 @@ $(document).ready(function(){
|
|||
})
|
||||
.on('click', '.btn-create-asset', function () {
|
||||
var url = "{% url 'assets:asset-create' %}";
|
||||
var nodes = zTree.getSelectedNodes();
|
||||
var current_node;
|
||||
if (nodes && nodes.length ===1 ){
|
||||
current_node = nodes[0];
|
||||
url += "?node_id=" + current_node.node_id;
|
||||
if (current_node_id) {
|
||||
url += "?node_id=" + current_node_id;
|
||||
}
|
||||
window.open(url, '_self');
|
||||
})
|
||||
.on('click', '.btn-refresh-hardware', function () {
|
||||
var url = "{% url 'api-assets:node-refresh-hardware-info' pk=DEFAULT_PK %}";
|
||||
var nodes = zTree.getSelectedNodes();
|
||||
var current_node;
|
||||
if (nodes && nodes.length ===1 ){
|
||||
current_node = nodes[0];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
var the_url = url.replace("{{ DEFAULT_PK }}", current_node.node_id);
|
||||
var the_url = url.replace("{{ DEFAULT_PK }}", current_node_id);
|
||||
function success(data) {
|
||||
rMenu.css({"visibility" : "hidden"});
|
||||
var task_id = data.task;
|
||||
|
@ -538,15 +522,10 @@ $(document).ready(function(){
|
|||
})
|
||||
.on('click', '.btn-test-connective', function () {
|
||||
var url = "{% url 'api-assets:node-test-connective' pk=DEFAULT_PK %}";
|
||||
var nodes = zTree.getSelectedNodes();
|
||||
var current_node;
|
||||
if (nodes && nodes.length ===1 ){
|
||||
current_node = nodes[0];
|
||||
} else {
|
||||
if (!current_node_id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var the_url = url.replace("{{ DEFAULT_PK }}", current_node.node_id);
|
||||
var the_url = url.replace("{{ DEFAULT_PK }}", current_node_id);
|
||||
function success(data) {
|
||||
rMenu.css({"visibility" : "hidden"});
|
||||
var task_id = data.task;
|
||||
|
@ -574,6 +553,10 @@ $(document).ready(function(){
|
|||
setCookie('show_current_asset', '');
|
||||
location.reload();
|
||||
})
|
||||
.on('click', '.btn-test-connective', function () {
|
||||
hideRMenu();
|
||||
|
||||
})
|
||||
.on('click', '.btn_asset_delete', function () {
|
||||
var $this = $(this);
|
||||
var $data_table = $("#asset_list_table").DataTable();
|
||||
|
@ -667,11 +650,8 @@ $(document).ready(function(){
|
|||
}
|
||||
|
||||
function doRemove() {
|
||||
var current_node;
|
||||
var nodes = zTree.getSelectedNodes();
|
||||
if (nodes && nodes.length === 1) {
|
||||
current_node = nodes[0]
|
||||
} else {
|
||||
if (!current_node_id) {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -684,7 +664,7 @@ $(document).ready(function(){
|
|||
};
|
||||
|
||||
APIUpdateAttr({
|
||||
'url': '/api/assets/v1/nodes/' + current_node.node_id + '/assets/remove/',
|
||||
'url': '/api/assets/v1/nodes/' + current_node_id + '/assets/remove/',
|
||||
'method': 'PUT',
|
||||
'body': JSON.stringify(data),
|
||||
'success': success
|
||||
|
@ -713,11 +693,7 @@ $(document).ready(function(){
|
|||
})
|
||||
.on('click', '#btn_asset_modal_confirm', function () {
|
||||
var assets_selected = asset_table2.selected;
|
||||
var current_node;
|
||||
var nodes = zTree.getSelectedNodes();
|
||||
if (nodes && nodes.length === 1) {
|
||||
current_node = nodes[0]
|
||||
} else {
|
||||
if (!current_node_id) {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -729,9 +705,9 @@ $(document).ready(function(){
|
|||
|
||||
var url = '';
|
||||
if (update_node_action === "move") {
|
||||
url = "{% url 'api-assets:node-replace-assets' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", current_node.node_id);
|
||||
url = "{% url 'api-assets:node-replace-assets' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", current_node_id);
|
||||
} else {
|
||||
url = "{% url 'api-assets:node-add-assets' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", current_node.node_id);
|
||||
url = "{% url 'api-assets:node-add-assets' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", current_node_id);
|
||||
}
|
||||
|
||||
APIUpdateAttr({
|
||||
|
|
|
@ -53,6 +53,8 @@ urlpatterns = [
|
|||
path('system-user/<uuid:pk>/cmd-filter-rules/',
|
||||
api.SystemUserCommandFilterRuleListApi.as_view(), name='system-user-cmd-filter-rule-list'),
|
||||
|
||||
path('nodes/tree/', api.NodeListAsTreeApi.as_view(), name='node-tree'),
|
||||
path('nodes/children/tree/', api.NodeChildrenAsTreeApi.as_view(), name='node-children-tree'),
|
||||
path('nodes/<uuid:pk>/children/',
|
||||
api.NodeChildrenApi.as_view(), name='node-children'),
|
||||
path('nodes/children/', api.NodeChildrenApi.as_view(), name='node-children-2'),
|
||||
|
|
|
@ -216,7 +216,6 @@ class AssetExportView(LoginRequiredMixin, View):
|
|||
return HttpResponse('Json object not valid', status=400)
|
||||
|
||||
if not assets_id:
|
||||
print(node_id)
|
||||
node = get_object_or_none(Node, id=node_id) if node_id else Node.root()
|
||||
assets = node.get_all_assets()
|
||||
for asset in assets:
|
||||
|
|
|
@ -356,6 +356,7 @@ FILE_UPLOAD_DIRECTORY_PERMISSIONS = 0o755
|
|||
|
||||
# OTP settings
|
||||
OTP_ISSUER_NAME = CONFIG.OTP_ISSUER_NAME
|
||||
OTP_VALID_WINDOW = CONFIG.OTP_VALID_WINDOW
|
||||
|
||||
# Auth LDAP settings
|
||||
AUTH_LDAP = False
|
||||
|
|
Binary file not shown.
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: Jumpserver 0.3.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2018-12-17 10:14+0800\n"
|
||||
"POT-Creation-Date: 2018-12-17 17:51+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"
|
||||
|
@ -17,19 +17,11 @@ msgstr ""
|
|||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: assets/api/node.py:58
|
||||
msgid "You can't update the root node name"
|
||||
msgstr "不能修改根节点名称"
|
||||
|
||||
#: assets/api/node.py:82
|
||||
msgid "New node {}"
|
||||
msgstr "新节点 {}"
|
||||
|
||||
#: assets/api/node.py:222
|
||||
#: assets/api/node.py:261
|
||||
msgid "Update node asset hardware information: {}"
|
||||
msgstr "更新节点资产硬件信息: {}"
|
||||
|
||||
#: assets/api/node.py:236
|
||||
#: assets/api/node.py:275
|
||||
msgid "Test if the assets under the node are connectable: {}"
|
||||
msgstr "测试节点下资产是否可连接: {}"
|
||||
|
||||
|
@ -70,12 +62,12 @@ msgid "Domain"
|
|||
msgstr "网域"
|
||||
|
||||
#: assets/forms/asset.py:41 assets/forms/asset.py:66 assets/forms/asset.py:80
|
||||
#: assets/forms/asset.py:131 assets/models/node.py:28
|
||||
#: assets/forms/asset.py:131 assets/models/node.py:31
|
||||
#: assets/templates/assets/asset_create.html:30
|
||||
#: assets/templates/assets/asset_update.html:35 perms/forms.py:37
|
||||
#: perms/forms.py:44 perms/models.py:79
|
||||
#: perms/templates/perms/asset_permission_list.html:57
|
||||
#: perms/templates/perms/asset_permission_list.html:151
|
||||
#: perms/templates/perms/asset_permission_list.html:117
|
||||
#: xpack/plugins/cloud/models.py:122
|
||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:63
|
||||
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:66
|
||||
|
@ -116,7 +108,7 @@ msgid "Port"
|
|||
msgstr "端口"
|
||||
|
||||
#: assets/forms/domain.py:15 assets/forms/label.py:13
|
||||
#: assets/models/asset.py:260 assets/templates/assets/admin_user_list.html:28
|
||||
#: assets/models/asset.py:290 assets/templates/assets/admin_user_list.html:28
|
||||
#: assets/templates/assets/domain_detail.html:60
|
||||
#: assets/templates/assets/domain_list.html:26
|
||||
#: assets/templates/assets/label_list.html:16
|
||||
|
@ -126,7 +118,7 @@ msgstr "端口"
|
|||
#: perms/models.py:31
|
||||
#: perms/templates/perms/asset_permission_create_update.html:40
|
||||
#: perms/templates/perms/asset_permission_list.html:56
|
||||
#: perms/templates/perms/asset_permission_list.html:148
|
||||
#: perms/templates/perms/asset_permission_list.html:114
|
||||
#: terminal/backends/command/models.py:13 terminal/models.py:138
|
||||
#: terminal/templates/terminal/command_list.html:40
|
||||
#: terminal/templates/terminal/command_list.html:73
|
||||
|
@ -619,7 +611,7 @@ msgstr "默认资产组"
|
|||
#: perms/models.py:29
|
||||
#: perms/templates/perms/asset_permission_create_update.html:36
|
||||
#: perms/templates/perms/asset_permission_list.html:54
|
||||
#: perms/templates/perms/asset_permission_list.html:142 templates/index.html:87
|
||||
#: perms/templates/perms/asset_permission_list.html:108 templates/index.html:87
|
||||
#: terminal/backends/command/models.py:12 terminal/models.py:137
|
||||
#: terminal/templates/terminal/command_list.html:32
|
||||
#: terminal/templates/terminal/command_list.html:72
|
||||
|
@ -634,7 +626,7 @@ msgstr "默认资产组"
|
|||
msgid "User"
|
||||
msgstr "用户"
|
||||
|
||||
#: assets/models/label.py:19 assets/models/node.py:20
|
||||
#: assets/models/label.py:19 assets/models/node.py:21
|
||||
#: assets/templates/assets/label_list.html:15 common/models.py:30
|
||||
msgid "Value"
|
||||
msgstr "值"
|
||||
|
@ -643,10 +635,14 @@ msgstr "值"
|
|||
msgid "Category"
|
||||
msgstr "分类"
|
||||
|
||||
#: assets/models/node.py:19
|
||||
#: assets/models/node.py:20
|
||||
msgid "Key"
|
||||
msgstr ""
|
||||
|
||||
#: assets/models/node.py:127
|
||||
msgid "New node"
|
||||
msgstr "新节点"
|
||||
|
||||
#: assets/models/user.py:109
|
||||
msgid "Automatic login"
|
||||
msgstr "自动登录"
|
||||
|
@ -702,7 +698,7 @@ msgstr "登录模式"
|
|||
#: perms/models.py:33 perms/models.py:81
|
||||
#: perms/templates/perms/asset_permission_detail.html:140
|
||||
#: perms/templates/perms/asset_permission_list.html:58
|
||||
#: perms/templates/perms/asset_permission_list.html:154 templates/_nav.html:25
|
||||
#: perms/templates/perms/asset_permission_list.html:120 templates/_nav.html:25
|
||||
#: terminal/backends/command/models.py:14 terminal/models.py:139
|
||||
#: terminal/templates/terminal/command_list.html:48
|
||||
#: terminal/templates/terminal/command_list.html:74
|
||||
|
@ -734,7 +730,7 @@ msgid "Asset may not be support ansible, skipped: {}"
|
|||
msgstr "资产或许不支持ansible, 跳过: {}"
|
||||
|
||||
#: assets/tasks.py:111 assets/tasks.py:210 assets/tasks.py:325
|
||||
#: assets/tasks.py:431
|
||||
#: assets/tasks.py:432
|
||||
msgid "No assets matched, stop task"
|
||||
msgstr "没有匹配到资产,结束任务"
|
||||
|
||||
|
@ -742,10 +738,6 @@ msgstr "没有匹配到资产,结束任务"
|
|||
msgid "Update asset hardware info: {}"
|
||||
msgstr "更新资产硬件信息: {}"
|
||||
|
||||
#: assets/tasks.py:148
|
||||
msgid "Update assets hardware info period"
|
||||
msgstr "定期更新资产硬件信息"
|
||||
|
||||
#: assets/tasks.py:230
|
||||
msgid "Test admin user connectability period: {}"
|
||||
msgstr "定期测试管理账号可连接性: {}"
|
||||
|
@ -758,11 +750,11 @@ msgstr "测试管理行号可连接性: {}"
|
|||
msgid "Test assets connectability"
|
||||
msgstr "测试资产可连接性"
|
||||
|
||||
#: assets/tasks.py:251 assets/tasks.py:316 assets/tasks.py:422
|
||||
#: assets/tasks.py:251 assets/tasks.py:316 assets/tasks.py:423
|
||||
msgid "Asset has been disabled, skip: {}"
|
||||
msgstr "资产被禁用,跳过:{}"
|
||||
|
||||
#: assets/tasks.py:255 assets/tasks.py:320 assets/tasks.py:426
|
||||
#: assets/tasks.py:255 assets/tasks.py:320 assets/tasks.py:427
|
||||
msgid "Asset may not be support ansible, skip: {}"
|
||||
msgstr "资产或许不支持ansible, 跳过: {}"
|
||||
|
||||
|
@ -782,20 +774,16 @@ msgstr "测试系统用户可连接性: {}"
|
|||
msgid "Test system user connectability: {} => {}"
|
||||
msgstr "测试系统用户可连接性: {} => {}"
|
||||
|
||||
#: assets/tasks.py:359
|
||||
msgid "Test system user connectability period: {}"
|
||||
msgstr "定期测试系统用户可连接性: {}"
|
||||
|
||||
#: assets/tasks.py:413
|
||||
#: assets/tasks.py:414
|
||||
msgid ""
|
||||
"Push system user task skip, auto push not enable or protocol is not ssh: {}"
|
||||
msgstr "推送系统用户任务跳过,自动推送没有打开,或协议不是ssh: {}"
|
||||
|
||||
#: assets/tasks.py:444 assets/tasks.py:458
|
||||
#: assets/tasks.py:445 assets/tasks.py:459
|
||||
msgid "Push system users to assets: {}"
|
||||
msgstr "推送系统用户到入资产: {}"
|
||||
|
||||
#: assets/tasks.py:450
|
||||
#: assets/tasks.py:451
|
||||
msgid "Push system users to asset: {} => {}"
|
||||
msgstr "推送系统用户到入资产: {} => {}"
|
||||
|
||||
|
@ -1015,7 +1003,7 @@ msgstr "测试"
|
|||
#: assets/templates/assets/admin_user_detail.html:24
|
||||
#: assets/templates/assets/admin_user_list.html:88
|
||||
#: assets/templates/assets/asset_detail.html:24
|
||||
#: assets/templates/assets/asset_list.html:171
|
||||
#: assets/templates/assets/asset_list.html:174
|
||||
#: assets/templates/assets/cmd_filter_detail.html:29
|
||||
#: assets/templates/assets/cmd_filter_list.html:57
|
||||
#: assets/templates/assets/cmd_filter_rule_list.html:86
|
||||
|
@ -1027,7 +1015,7 @@ msgstr "测试"
|
|||
#: assets/templates/assets/system_user_detail.html:26
|
||||
#: assets/templates/assets/system_user_list.html:92 audits/models.py:32
|
||||
#: perms/templates/perms/asset_permission_detail.html:30
|
||||
#: perms/templates/perms/asset_permission_list.html:200
|
||||
#: perms/templates/perms/asset_permission_list.html:166
|
||||
#: terminal/templates/terminal/terminal_detail.html:16
|
||||
#: terminal/templates/terminal/terminal_list.html:71
|
||||
#: users/templates/users/user_detail.html:25
|
||||
|
@ -1047,7 +1035,7 @@ msgstr "更新"
|
|||
#: assets/templates/assets/admin_user_detail.html:28
|
||||
#: assets/templates/assets/admin_user_list.html:89
|
||||
#: assets/templates/assets/asset_detail.html:28
|
||||
#: assets/templates/assets/asset_list.html:172
|
||||
#: assets/templates/assets/asset_list.html:175
|
||||
#: assets/templates/assets/cmd_filter_detail.html:33
|
||||
#: assets/templates/assets/cmd_filter_list.html:58
|
||||
#: assets/templates/assets/cmd_filter_rule_list.html:87
|
||||
|
@ -1062,7 +1050,7 @@ msgstr "更新"
|
|||
#: common/templates/common/terminal_setting.html:112
|
||||
#: ops/templates/ops/task_list.html:72
|
||||
#: perms/templates/perms/asset_permission_detail.html:34
|
||||
#: perms/templates/perms/asset_permission_list.html:201
|
||||
#: perms/templates/perms/asset_permission_list.html:167
|
||||
#: terminal/templates/terminal/terminal_list.html:73
|
||||
#: users/templates/users/user_detail.html:30
|
||||
#: users/templates/users/user_group_detail.html:32
|
||||
|
@ -1089,7 +1077,7 @@ msgstr "选择节点"
|
|||
|
||||
#: assets/templates/assets/admin_user_detail.html:100
|
||||
#: assets/templates/assets/asset_detail.html:208
|
||||
#: assets/templates/assets/asset_list.html:633
|
||||
#: assets/templates/assets/asset_list.html:623
|
||||
#: assets/templates/assets/cmd_filter_detail.html:106
|
||||
#: assets/templates/assets/system_user_asset.html:112
|
||||
#: assets/templates/assets/system_user_detail.html:182
|
||||
|
@ -1197,6 +1185,7 @@ msgid "Refresh hardware"
|
|||
msgstr "更新硬件信息"
|
||||
|
||||
#: assets/templates/assets/asset_detail.html:171
|
||||
#: assets/templates/assets/asset_list.html:139
|
||||
msgid "Refresh"
|
||||
msgstr "刷新"
|
||||
|
||||
|
@ -1293,27 +1282,27 @@ msgstr "仅显示当前节点资产"
|
|||
msgid "Displays all child node assets"
|
||||
msgstr "显示所有子节点资产"
|
||||
|
||||
#: assets/templates/assets/asset_list.html:208
|
||||
#: assets/templates/assets/asset_list.html:213
|
||||
msgid "Create node failed"
|
||||
msgstr "创建节点失败"
|
||||
|
||||
#: assets/templates/assets/asset_list.html:220
|
||||
#: assets/templates/assets/asset_list.html:225
|
||||
msgid "Have child node, cancel"
|
||||
msgstr "存在子节点,不能删除"
|
||||
|
||||
#: assets/templates/assets/asset_list.html:222
|
||||
#: assets/templates/assets/asset_list.html:227
|
||||
msgid "Have assets, cancel"
|
||||
msgstr "存在资产,不能删除"
|
||||
|
||||
#: assets/templates/assets/asset_list.html:293
|
||||
#: assets/templates/assets/asset_list.html:298
|
||||
msgid "Rename success"
|
||||
msgstr "重命名成功"
|
||||
|
||||
#: assets/templates/assets/asset_list.html:294
|
||||
#: assets/templates/assets/asset_list.html:299
|
||||
msgid "Rename failed, do not change the root node name"
|
||||
msgstr "重命名失败,不能更改root节点的名称"
|
||||
|
||||
#: assets/templates/assets/asset_list.html:627
|
||||
#: assets/templates/assets/asset_list.html:617
|
||||
#: assets/templates/assets/system_user_list.html:137
|
||||
#: users/templates/users/user_detail.html:380
|
||||
#: users/templates/users/user_detail.html:406
|
||||
|
@ -1323,11 +1312,11 @@ msgstr "重命名失败,不能更改root节点的名称"
|
|||
msgid "Are you sure?"
|
||||
msgstr "你确认吗?"
|
||||
|
||||
#: assets/templates/assets/asset_list.html:628
|
||||
#: assets/templates/assets/asset_list.html:618
|
||||
msgid "This will delete the selected assets !!!"
|
||||
msgstr "删除选择资产"
|
||||
|
||||
#: assets/templates/assets/asset_list.html:631
|
||||
#: assets/templates/assets/asset_list.html:621
|
||||
#: assets/templates/assets/system_user_list.html:141
|
||||
#: common/templates/common/terminal_setting.html:163
|
||||
#: users/templates/users/user_detail.html:384
|
||||
|
@ -1340,16 +1329,16 @@ msgstr "删除选择资产"
|
|||
msgid "Cancel"
|
||||
msgstr "取消"
|
||||
|
||||
#: assets/templates/assets/asset_list.html:637
|
||||
#: assets/templates/assets/asset_list.html:627
|
||||
msgid "Asset Deleted."
|
||||
msgstr "已被删除"
|
||||
|
||||
#: assets/templates/assets/asset_list.html:638
|
||||
#: assets/templates/assets/asset_list.html:643
|
||||
#: assets/templates/assets/asset_list.html:628
|
||||
#: assets/templates/assets/asset_list.html:633
|
||||
msgid "Asset Delete"
|
||||
msgstr "删除"
|
||||
|
||||
#: assets/templates/assets/asset_list.html:642
|
||||
#: assets/templates/assets/asset_list.html:632
|
||||
msgid "Asset Deleting failed."
|
||||
msgstr "删除失败"
|
||||
|
||||
|
@ -1586,7 +1575,7 @@ msgstr "批量更新资产"
|
|||
msgid "Update asset"
|
||||
msgstr "更新资产"
|
||||
|
||||
#: assets/views/asset.py:293
|
||||
#: assets/views/asset.py:292
|
||||
msgid "already exists"
|
||||
msgstr "已经存在"
|
||||
|
||||
|
@ -1966,69 +1955,69 @@ msgstr "全部"
|
|||
msgid "Auto"
|
||||
msgstr "自动"
|
||||
|
||||
#: common/forms.py:144
|
||||
#: common/forms.py:146
|
||||
msgid "Password auth"
|
||||
msgstr "密码认证"
|
||||
|
||||
#: common/forms.py:147
|
||||
#: common/forms.py:149
|
||||
msgid "Public key auth"
|
||||
msgstr "密钥认证"
|
||||
|
||||
#: common/forms.py:150
|
||||
#: common/forms.py:152
|
||||
msgid "Heartbeat interval"
|
||||
msgstr "心跳间隔"
|
||||
|
||||
#: common/forms.py:150 ops/models/adhoc.py:38
|
||||
#: common/forms.py:152 ops/models/adhoc.py:38
|
||||
msgid "Units: seconds"
|
||||
msgstr "单位: 秒"
|
||||
|
||||
#: common/forms.py:153
|
||||
#: common/forms.py:155
|
||||
msgid "List sort by"
|
||||
msgstr "资产列表排序"
|
||||
|
||||
#: common/forms.py:156
|
||||
#: common/forms.py:158
|
||||
msgid "List page size"
|
||||
msgstr "资产列表页面大小"
|
||||
|
||||
#: common/forms.py:168
|
||||
#: common/forms.py:170
|
||||
msgid "MFA Secondary certification"
|
||||
msgstr "MFA 二次认证"
|
||||
|
||||
#: common/forms.py:170
|
||||
#: common/forms.py:172
|
||||
msgid ""
|
||||
"After opening, the user login must use MFA secondary authentication (valid "
|
||||
"for all users, including administrators)"
|
||||
msgstr "开启后,用户登录必须使用MFA二次认证(对所有用户有效,包括管理员)"
|
||||
|
||||
#: common/forms.py:177
|
||||
#: common/forms.py:179
|
||||
msgid "Limit the number of login failures"
|
||||
msgstr "限制登录失败次数"
|
||||
|
||||
#: common/forms.py:182
|
||||
#: common/forms.py:184
|
||||
msgid "No logon interval"
|
||||
msgstr "禁止登录时间间隔"
|
||||
|
||||
#: common/forms.py:184
|
||||
#: common/forms.py:186
|
||||
msgid ""
|
||||
"Tip: (unit/minute) if the user has failed to log in for a limited number of "
|
||||
"times, no login is allowed during this time interval."
|
||||
msgstr ""
|
||||
"提示:(单位:分)当用户登录失败次数达到限制后,那么在此时间间隔内禁止登录"
|
||||
|
||||
#: common/forms.py:191
|
||||
#: common/forms.py:193
|
||||
msgid "Connection max idle time"
|
||||
msgstr "SSH最大空闲时间"
|
||||
|
||||
#: common/forms.py:193
|
||||
#: common/forms.py:195
|
||||
msgid ""
|
||||
"If idle time more than it, disconnect connection(only ssh now) Unit: minute"
|
||||
msgstr "提示:(单位:分)如果超过该配置没有操作,连接会被断开(仅ssh)"
|
||||
|
||||
#: common/forms.py:199
|
||||
#: common/forms.py:201
|
||||
msgid "Password expiration time"
|
||||
msgstr "密码过期时间"
|
||||
|
||||
#: common/forms.py:202
|
||||
#: common/forms.py:204
|
||||
msgid ""
|
||||
"Tip: (unit: day) If the user does not update the password during the time, "
|
||||
"the user password will expire failure;The password expiration reminder mail "
|
||||
|
@ -2038,45 +2027,45 @@ msgstr ""
|
|||
"提示:(单位:天)如果用户在此期间没有更新密码,用户密码将过期失效; 密码过期"
|
||||
"提醒邮件将在密码过期前5天内由系统(每天)自动发送给用户"
|
||||
|
||||
#: common/forms.py:211
|
||||
#: common/forms.py:213
|
||||
msgid "Password minimum length"
|
||||
msgstr "密码最小长度 "
|
||||
|
||||
#: common/forms.py:217
|
||||
#: common/forms.py:219
|
||||
msgid "Must contain capital letters"
|
||||
msgstr "必须包含大写字母"
|
||||
|
||||
#: common/forms.py:219
|
||||
#: common/forms.py:221
|
||||
msgid ""
|
||||
"After opening, the user password changes and resets must contain uppercase "
|
||||
"letters"
|
||||
msgstr "开启后,用户密码修改、重置必须包含大写字母"
|
||||
|
||||
#: common/forms.py:225
|
||||
#: common/forms.py:227
|
||||
msgid "Must contain lowercase letters"
|
||||
msgstr "必须包含小写字母"
|
||||
|
||||
#: common/forms.py:226
|
||||
#: common/forms.py:228
|
||||
msgid ""
|
||||
"After opening, the user password changes and resets must contain lowercase "
|
||||
"letters"
|
||||
msgstr "开启后,用户密码修改、重置必须包含小写字母"
|
||||
|
||||
#: common/forms.py:232
|
||||
#: common/forms.py:234
|
||||
msgid "Must contain numeric characters"
|
||||
msgstr "必须包含数字字符"
|
||||
|
||||
#: common/forms.py:233
|
||||
#: common/forms.py:235
|
||||
msgid ""
|
||||
"After opening, the user password changes and resets must contain numeric "
|
||||
"characters"
|
||||
msgstr "开启后,用户密码修改、重置必须包含数字字符"
|
||||
|
||||
#: common/forms.py:239
|
||||
#: common/forms.py:241
|
||||
msgid "Must contain special characters"
|
||||
msgstr "必须包含特殊字符"
|
||||
|
||||
#: common/forms.py:240
|
||||
#: common/forms.py:242
|
||||
msgid ""
|
||||
"After opening, the user password changes and resets must contain special "
|
||||
"characters"
|
||||
|
@ -2370,7 +2359,7 @@ msgid "Version detail"
|
|||
msgstr "版本详情"
|
||||
|
||||
#: ops/templates/ops/adhoc_detail.html:22
|
||||
#: ops/templates/ops/adhoc_history.html:22 ops/views/adhoc.py:124
|
||||
#: ops/templates/ops/adhoc_history.html:22 ops/views/adhoc.py:127
|
||||
msgid "Version run history"
|
||||
msgstr "执行历史"
|
||||
|
||||
|
@ -2434,7 +2423,7 @@ msgstr "失败/成功/总"
|
|||
msgid "Version"
|
||||
msgstr "版本"
|
||||
|
||||
#: ops/templates/ops/adhoc_history_detail.html:19 ops/views/adhoc.py:137
|
||||
#: ops/templates/ops/adhoc_history_detail.html:19 ops/views/adhoc.py:140
|
||||
msgid "Run history detail"
|
||||
msgstr "执行历史详情"
|
||||
|
||||
|
@ -2480,12 +2469,12 @@ msgid "Finished"
|
|||
msgstr "结束"
|
||||
|
||||
#: ops/templates/ops/task_adhoc.html:19 ops/templates/ops/task_detail.html:20
|
||||
#: ops/templates/ops/task_history.html:19 ops/views/adhoc.py:72
|
||||
#: ops/templates/ops/task_history.html:19 ops/views/adhoc.py:75
|
||||
msgid "Task detail"
|
||||
msgstr "任务详情"
|
||||
|
||||
#: ops/templates/ops/task_adhoc.html:22 ops/templates/ops/task_detail.html:23
|
||||
#: ops/templates/ops/task_history.html:22 ops/views/adhoc.py:85
|
||||
#: ops/templates/ops/task_history.html:22 ops/views/adhoc.py:88
|
||||
msgid "Task versions"
|
||||
msgstr "任务各版本"
|
||||
|
||||
|
@ -2532,9 +2521,9 @@ msgstr "任务开始: "
|
|||
msgid "Update task content: {}"
|
||||
msgstr "更新任务内容: {}"
|
||||
|
||||
#: ops/views/adhoc.py:49 ops/views/adhoc.py:71 ops/views/adhoc.py:84
|
||||
#: ops/views/adhoc.py:97 ops/views/adhoc.py:110 ops/views/adhoc.py:123
|
||||
#: ops/views/adhoc.py:136 ops/views/command.py:43 ops/views/command.py:67
|
||||
#: ops/views/adhoc.py:49 ops/views/adhoc.py:74 ops/views/adhoc.py:87
|
||||
#: ops/views/adhoc.py:100 ops/views/adhoc.py:113 ops/views/adhoc.py:126
|
||||
#: ops/views/adhoc.py:139 ops/views/command.py:43 ops/views/command.py:67
|
||||
msgid "Ops"
|
||||
msgstr "作业中心"
|
||||
|
||||
|
@ -2542,7 +2531,7 @@ msgstr "作业中心"
|
|||
msgid "Task list"
|
||||
msgstr "任务列表"
|
||||
|
||||
#: ops/views/adhoc.py:98
|
||||
#: ops/views/adhoc.py:101
|
||||
msgid "Task run history"
|
||||
msgstr "执行历史"
|
||||
|
||||
|
@ -2557,7 +2546,7 @@ msgstr "组织管理"
|
|||
|
||||
#: perms/forms.py:31 perms/models.py:30 perms/models.py:80
|
||||
#: perms/templates/perms/asset_permission_list.html:55
|
||||
#: perms/templates/perms/asset_permission_list.html:145 templates/_nav.html:14
|
||||
#: perms/templates/perms/asset_permission_list.html:111 templates/_nav.html:14
|
||||
#: users/forms.py:284 users/models/group.py:26 users/models/user.py:59
|
||||
#: users/templates/users/_select_user_modal.html:16
|
||||
#: users/templates/users/user_detail.html:211
|
||||
|
@ -4486,50 +4475,6 @@ msgstr "AWS (中国)"
|
|||
msgid "AWS (International)"
|
||||
msgstr "AWS (国际)"
|
||||
|
||||
#: xpack/plugins/cloud/providers/base.py:76
|
||||
msgid "任务执行开始: {}\n"
|
||||
msgstr ""
|
||||
|
||||
#: xpack/plugins/cloud/providers/base.py:79
|
||||
msgid "检测账户有效性: {}"
|
||||
msgstr ""
|
||||
|
||||
#: xpack/plugins/cloud/providers/base.py:82
|
||||
msgid "账户无效!\n"
|
||||
msgstr ""
|
||||
|
||||
#: xpack/plugins/cloud/providers/base.py:86
|
||||
msgid "账户有效!\n"
|
||||
msgstr ""
|
||||
|
||||
#: xpack/plugins/cloud/providers/base.py:90
|
||||
msgid ""
|
||||
"\n"
|
||||
"任务执行结束!\n"
|
||||
msgstr ""
|
||||
|
||||
#: xpack/plugins/cloud/providers/base.py:91
|
||||
msgid ""
|
||||
"查看任务详细信息路径: XPack -> 云管中心 -> 任务列表 -> 任务详情(点击任务名"
|
||||
"称) -> 查看同步历史列表/实例列表\n"
|
||||
msgstr ""
|
||||
|
||||
#: xpack/plugins/cloud/providers/base.py:126
|
||||
msgid "同步实例列表: {}"
|
||||
msgstr ""
|
||||
|
||||
#: xpack/plugins/cloud/providers/base.py:135
|
||||
msgid "同步地域列表: {}\n"
|
||||
msgstr ""
|
||||
|
||||
#: xpack/plugins/cloud/providers/base.py:138
|
||||
msgid "地域: {}"
|
||||
msgstr ""
|
||||
|
||||
#: xpack/plugins/cloud/providers/base.py:148
|
||||
msgid "实例: {}, 地域: {}"
|
||||
msgstr ""
|
||||
|
||||
#: xpack/plugins/cloud/providers/qcloud.py:14
|
||||
msgid "Qcloud"
|
||||
msgstr "腾讯云"
|
||||
|
@ -4661,6 +4606,15 @@ msgstr "创建组织"
|
|||
msgid "Update org"
|
||||
msgstr "更新组织"
|
||||
|
||||
#~ msgid "You can't update the root node name"
|
||||
#~ msgstr "不能修改根节点名称"
|
||||
|
||||
#~ msgid "Update assets hardware info period"
|
||||
#~ msgstr "定期更新资产硬件信息"
|
||||
|
||||
#~ msgid "Test system user connectability period: {}"
|
||||
#~ msgstr "定期测试系统用户可连接性: {}"
|
||||
|
||||
#~ msgid "Date finished"
|
||||
#~ msgstr "结束日期"
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ from orgs.utils import set_to_root_org
|
|||
from .utils import AssetPermissionUtil
|
||||
from .models import AssetPermission
|
||||
from .hands import AssetGrantedSerializer, User, UserGroup, Asset, Node, \
|
||||
NodeGrantedSerializer, SystemUser, NodeSerializer
|
||||
SystemUser, NodeSerializer
|
||||
from . import serializers
|
||||
from .mixins import AssetsFilterMixin
|
||||
|
||||
|
@ -150,7 +150,7 @@ class UserGrantedNodesWithAssetsApi(AssetsFilterMixin, ListAPIView):
|
|||
用户授权的节点并带着节点下资产的api
|
||||
"""
|
||||
permission_classes = (IsOrgAdminOrAppUser,)
|
||||
serializer_class = NodeGrantedSerializer
|
||||
serializer_class = serializers.NodeGrantedSerializer
|
||||
|
||||
def change_org_if_need(self):
|
||||
if self.request.user.is_superuser or \
|
||||
|
@ -360,7 +360,7 @@ class UserGroupGrantedNodesApi(ListAPIView):
|
|||
|
||||
class UserGroupGrantedNodesWithAssetsApi(ListAPIView):
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
serializer_class = NodeGrantedSerializer
|
||||
serializer_class = serializers.NodeGrantedSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
user_group_id = self.kwargs.get('pk', '')
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
from common.permissions import AdminUserRequiredMixin
|
||||
from users.models import User, UserGroup
|
||||
from assets.models import Asset, SystemUser, Node
|
||||
from assets.serializers import AssetGrantedSerializer, NodeGrantedSerializer, NodeSerializer
|
||||
from assets.serializers import AssetGrantedSerializer, NodeSerializer
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -83,6 +83,35 @@ class AssetPermissionNodeSerializer(serializers.ModelSerializer):
|
|||
return obj.parent_key
|
||||
|
||||
|
||||
class NodeGrantedSerializer(serializers.ModelSerializer):
|
||||
"""
|
||||
授权资产组
|
||||
"""
|
||||
assets_granted = AssetGrantedSerializer(many=True, read_only=True)
|
||||
assets_amount = serializers.SerializerMethodField()
|
||||
parent = serializers.SerializerMethodField()
|
||||
name = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = Node
|
||||
fields = [
|
||||
'id', 'key', 'name', 'value', 'parent',
|
||||
'assets_granted', 'assets_amount', 'org_id',
|
||||
]
|
||||
|
||||
@staticmethod
|
||||
def get_assets_amount(obj):
|
||||
return len(obj.assets_granted)
|
||||
|
||||
@staticmethod
|
||||
def get_name(obj):
|
||||
return obj.name
|
||||
|
||||
@staticmethod
|
||||
def get_parent(obj):
|
||||
return obj.parent.id
|
||||
|
||||
|
||||
class GrantedNodeSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Node
|
||||
|
|
|
@ -78,58 +78,24 @@ var zTree, table, show = 0;
|
|||
function onSelected(event, treeNode) {
|
||||
setCookie('node_selected', treeNode.id);
|
||||
var url = table.ajax.url();
|
||||
if (treeNode.is_node) {
|
||||
if (treeNode.meta.type === 'node') {
|
||||
url = setUrlParam(url, 'asset', "");
|
||||
url = setUrlParam(url, 'node', treeNode.node_id)
|
||||
url = setUrlParam(url, 'node', treeNode.meta.node.id)
|
||||
} else {
|
||||
url = setUrlParam(url, 'node', "");
|
||||
url = setUrlParam(url, 'asset', treeNode.node_id)
|
||||
url = setUrlParam(url, 'asset', treeNode.meta.asset.id)
|
||||
}
|
||||
setCookie('node_selected', treeNode.node_id);
|
||||
table.ajax.url(url);
|
||||
table.ajax.reload();
|
||||
}
|
||||
|
||||
function selectQueryNode() {
|
||||
var query_node_id = $.getUrlParam("node");
|
||||
var cookie_node_id = getCookie('node_selected');
|
||||
var node;
|
||||
var node_id;
|
||||
|
||||
if (query_node_id !== null) {
|
||||
node_id = query_node_id
|
||||
} else if (cookie_node_id !== null) {
|
||||
node_id = cookie_node_id;
|
||||
}
|
||||
|
||||
node = zTree.getNodesByParam("id", node_id, null);
|
||||
if (node){
|
||||
zTree.selectNode(node[0]);
|
||||
node.open = true;
|
||||
}
|
||||
}
|
||||
|
||||
function filter(treeId, parentNode, childNodes) {
|
||||
$.each(childNodes, function (index, value) {
|
||||
value["node_id"] = value["id"];
|
||||
value["id"] = value["tree_id"];
|
||||
if (value["tree_id"] !== value["tree_parent"]) {
|
||||
value["pId"] = value["tree_parent"];
|
||||
} else {
|
||||
value["isParent"] = true;
|
||||
}
|
||||
value['name'] = value['value'];
|
||||
value["iconSkin"] = value["is_node"] ? null : 'file';
|
||||
|
||||
{#value["pId"] = value["parent"];#}
|
||||
{#value["name"] = value["value"];#}
|
||||
value["isParent"] = value["is_node"];
|
||||
});
|
||||
return childNodes;
|
||||
}
|
||||
|
||||
function beforeAsync(treeId, treeNode) {
|
||||
return treeNode.is_node
|
||||
if (treeNode) {
|
||||
return treeNode.meta.type === 'node'
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
function makeLabel(data) {
|
||||
|
@ -235,9 +201,8 @@ function initTree() {
|
|||
},
|
||||
async: {
|
||||
enable: true,
|
||||
url: "{% url 'api-assets:node-children-2' %}?assets=1&all=",
|
||||
autoParam:["node_id=id", "name=n", "level=lv"],
|
||||
dataFilter: filter,
|
||||
url: "{% url 'api-assets:node-children-tree' %}?assets=1",
|
||||
autoParam:["id=key", "name=n", "level=lv"],
|
||||
type: 'get'
|
||||
},
|
||||
callback: {
|
||||
|
@ -245,25 +210,7 @@ function initTree() {
|
|||
beforeAsync: beforeAsync
|
||||
}
|
||||
};
|
||||
|
||||
var zNodes = [];
|
||||
$.get("{% url 'api-assets:node-children-2' %}?assets=1", function(data, status){
|
||||
$.each(data, function (index, value) {
|
||||
value["node_id"] = value["id"];
|
||||
value["id"] = value["tree_id"];
|
||||
if (value["tree_id"] !== value["tree_parent"]) {
|
||||
value["pId"] = value["tree_parent"];
|
||||
}
|
||||
value["isParent"] = value["is_node"];
|
||||
value['name'] = value['value'];
|
||||
value["iconSkin"] = value["is_node"] ? null : 'file';
|
||||
});
|
||||
zNodes = data;
|
||||
$.fn.zTree.init($("#assetTree"), setting, zNodes);
|
||||
zTree = $.fn.zTree.getZTreeObj("assetTree");
|
||||
var root = zTree.getNodes()[0];
|
||||
zTree.expandNode(root);
|
||||
});
|
||||
zTree = $.fn.zTree.init($("#assetTree"), setting);
|
||||
}
|
||||
|
||||
function toggle() {
|
||||
|
@ -299,10 +246,10 @@ $(document).ready(function(){
|
|||
var _nodes = [];
|
||||
var _assets = [];
|
||||
$.each(nodes, function (id, node) {
|
||||
if (node.is_node) {
|
||||
_nodes.push(node.node_id)
|
||||
if (node.meta.type === 'node') {
|
||||
_nodes.push(node.meta.node.id)
|
||||
} else {
|
||||
_assets.push(node.node_id)
|
||||
_assets.push(node.meta.asset.id)
|
||||
}
|
||||
});
|
||||
url += "?assets=" + _assets.join(",") + "&nodes=" + _nodes.join(",");
|
||||
|
|
|
@ -292,7 +292,8 @@ def check_otp_code(otp_secret_key, otp_code):
|
|||
if not otp_secret_key or not otp_code:
|
||||
return False
|
||||
totp = pyotp.TOTP(otp_secret_key)
|
||||
return totp.verify(otp_code)
|
||||
otp_valid_window = settings.OTP_VALID_WINDOW or 0
|
||||
return totp.verify(otp=otp_code, valid_window=otp_valid_window)
|
||||
|
||||
|
||||
def get_password_check_rules():
|
||||
|
|
|
@ -100,6 +100,9 @@ class Config:
|
|||
}
|
||||
AUTH_LDAP_START_TLS = False
|
||||
|
||||
#
|
||||
# OTP_VALID_WINDOW = 0
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
|
@ -200,6 +203,10 @@ class DockerConfig(Config):
|
|||
AUTH_LDAP_START_TLS = False
|
||||
|
||||
|
||||
#
|
||||
OTP_VALID_WINDOW = int(os.environ.get("OTP_VALID_WINDOW")) if os.environ.get("OTP_VALID_WINDOW") else 0
|
||||
|
||||
|
||||
# Default using Config settings, you can write if/else for different env
|
||||
config = DockerConfig()
|
||||
|
||||
|
|
|
@ -90,6 +90,9 @@ class Config:
|
|||
# AUTH_OPENID_CLIENT_ID = 'client-id'
|
||||
# AUTH_OPENID_CLIENT_SECRET = 'client-secret'
|
||||
|
||||
#
|
||||
# OTP_VALID_WINDOW = 0
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
|
|
Loading…
Reference in New Issue