diff --git a/apps/__init__.py b/apps/__init__.py index 90767858b..c6491d9fa 100644 --- a/apps/__init__.py +++ b/apps/__init__.py @@ -2,4 +2,4 @@ # -*- coding: utf-8 -*- # -__version__ = "1.3.0" +__version__ = "1.3.1" diff --git a/apps/assets/models/node.py b/apps/assets/models/node.py index fed8980ed..b63daf513 100644 --- a/apps/assets/models/node.py +++ b/apps/assets/models/node.py @@ -65,15 +65,25 @@ class Node(models.Model): key__regex=r'^{}:[0-9]+$'.format(self.key) ) + def get_children_with_self(self): + return self.__class__.objects.filter( + key__regex=r'^{0}$|^{0}:[0-9]+$'.format(self.key) + ) + def get_all_children(self): return self.__class__.objects.filter( key__startswith='{}:'.format(self.key) ) + def get_all_children_with_self(self): + return self.__class__.objects.filter( + key__regex=r'^{0}$|^{0}:'.format(self.key) + ) + def get_family(self): - children = list(self.get_all_children()) - children.append(self) - return children + ancestor = self.ancestor + children = self.get_all_children() + return [*tuple(ancestor), self, *tuple(children)] def get_assets(self): from .asset import Asset @@ -88,7 +98,7 @@ class Node(models.Model): if self.is_root(): assets = Asset.objects.all() else: - nodes = self.get_family() + nodes = self.get_all_children_with_self() assets = Asset.objects.filter(nodes__in=nodes).distinct() return assets @@ -108,18 +118,15 @@ class Node(models.Model): @property def parent(self): - if self.key == "0": - return self.__class__.root() - elif not self.key.startswith("0"): + if self.key == "0" or not self.key.startswith("0"): return self.__class__.root() parent_key = ":".join(self.key.split(":")[:-1]) try: parent = self.__class__.objects.get(key=parent_key) + return parent except Node.DoesNotExist: return self.__class__.root() - else: - return parent @parent.setter def parent(self, parent): @@ -127,14 +134,20 @@ class Node(models.Model): @property def ancestor(self): - if self.parent == self.__class__.root(): + _key = self.key.split(':') + ancestor_keys = [] + + if self.is_root(): return [self.__class__.root()] - else: - return [self.parent, *tuple(self.parent.ancestor)] + + for i in range(len(_key)-1): + _key.pop() + ancestor_keys.append(':'.join(_key)) + return self.__class__.objects.filter(key__in=ancestor_keys) @property - def ancestor_with_node(self): - ancestor = self.ancestor + def ancestor_with_self(self): + ancestor = list(self.ancestor) ancestor.insert(0, self) return ancestor diff --git a/apps/jumpserver/settings.py b/apps/jumpserver/settings.py index af72292f7..b81188b9d 100644 --- a/apps/jumpserver/settings.py +++ b/apps/jumpserver/settings.py @@ -229,7 +229,11 @@ LOGGING = { 'django_auth_ldap': { 'handlers': ['console', 'ansible_logs'], 'level': "INFO", - } + }, + # 'django.db': { + # 'handlers': ['console', 'file'], + # 'level': 'DEBUG' + # } } } diff --git a/apps/perms/api.py b/apps/perms/api.py index 8f663a0f4..e104cc1c4 100644 --- a/apps/perms/api.py +++ b/apps/perms/api.py @@ -41,7 +41,7 @@ class AssetPermissionViewSet(viewsets.ModelViewSet): asset = get_object_or_404(Asset, pk=asset_id) permissions = set(queryset.filter(assets=asset)) for node in asset.nodes.all(): - inherit_nodes.update(set(node.ancestor_with_node)) + inherit_nodes.update(set(node.ancestor_with_self)) elif node_id: node = get_object_or_404(Node, pk=node_id) permissions = set(queryset.filter(nodes=node)) diff --git a/apps/perms/utils.py b/apps/perms/utils.py index 7899cc5cb..d45f0f3d7 100644 --- a/apps/perms/utils.py +++ b/apps/perms/utils.py @@ -8,10 +8,35 @@ import copy from common.utils import set_or_append_attr_bulk, get_logger from .models import AssetPermission +from .hands import Node logger = get_logger(__file__) +class Tree: + def __init__(self): + self.__all_nodes = list(Node.objects.all()) + self.nodes = defaultdict(dict) + self.root = Node.root() + + def add_node(self, node): + if node in self.nodes: + return + else: + self.nodes[node] = defaultdict(set) + if node.key == self.root.key: + return + parent_key = ':'.join(node.key.split(':')[:-1]) + for n in self.__all_nodes: + if n.key == parent_key: + self.add_node(n) + break + + def add_nodes(self, nodes): + for node in nodes: + self.add_node(node) + + class AssetPermissionUtil: @staticmethod def get_user_permissions(user): @@ -181,25 +206,15 @@ class AssetPermissionUtil: :param user: :return: {node: {asset: set(su1, su2)}} """ - from assets.models import Node - unnode = Node(value='Unnode') - nodes = defaultdict(dict) - for _node in cls.get_user_nodes(user): - children = _node.get_family() - for node in children: - nodes[node] = defaultdict(set) - nodes[unnode] = defaultdict(set) + tree = Tree() _assets = cls.get_user_assets(user) for asset, _system_users in _assets.items(): _nodes = asset.get_nodes() - in_node = False + tree.add_nodes(_nodes) + for node in _nodes: - if node in nodes: - in_node = True - nodes[node][asset].update(_system_users) - if not in_node: - nodes[unnode][asset].update(_system_users) - return nodes + tree.nodes[node][asset].update(_system_users) + return tree.nodes @classmethod def get_system_user_assets(cls, system_user): @@ -254,7 +269,7 @@ class NodePermissionUtil: nodes = copy.deepcopy(nodes_directed) for node, system_users in nodes_directed.items(): - for child in node.get_family(): + for child in node.get_all_children_with_self(): nodes[child].update(system_users) return nodes diff --git a/apps/templates/_footer.html b/apps/templates/_footer.html index 8a723646d..10e607fa3 100644 --- a/apps/templates/_footer.html +++ b/apps/templates/_footer.html @@ -1,6 +1,6 @@ <div class="footer fixed"> <div class="pull-right"> - Version <strong>1.3.0-{% include '_build.html' %}</strong> GPLv2. + Version <strong>1.3.1-{% include '_build.html' %}</strong> GPLv2. <img style="display: none" src="http://www.jumpserver.org/img/evaluate_avatar1.jpg"> </div> <div> diff --git a/apps/terminal/api.py b/apps/terminal/api.py index 924a30dfd..fbbae5e22 100644 --- a/apps/terminal/api.py +++ b/apps/terminal/api.py @@ -109,10 +109,9 @@ class StatusViewSet(viewsets.ModelViewSet): task_serializer_class = TaskSerializer def create(self, request, *args, **kwargs): - if self.request.query_params.get("from_guacamole", None): - return Response({"msg": "From guacamole, not support now"}) - - self.handle_sessions() + from_gua = self.request.query_params.get("from_guacamole", None) + if not from_gua: + self.handle_sessions() super().create(request, *args, **kwargs) tasks = self.request.user.terminal.task_set.filter(is_finished=False) serializer = self.task_serializer_class(tasks, many=True) diff --git a/requirements/requirements.txt b/requirements/requirements.txt index af682f5ca..bcba2627c 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -3,10 +3,10 @@ ansible==2.4.2.0 asn1crypto==0.24.0 bcrypt==3.1.4 billiard==3.5.0.3 -boto3==1.6.4 -botocore==1.9.4 +boto3==1.6.5 +botocore==1.9.5 celery==4.1.0 -certifi==2017.11.5 +certifi==2018.1.18 cffi==1.11.2 chardet==3.0.4 configparser==3.5.0 @@ -31,7 +31,7 @@ ecdsa==0.13 elasticsearch==6.1.1 enum-compat==0.0.2 ephem==3.7.6.0 -eventlet==0.21.0 +eventlet==0.22.1 ForgeryPy==0.1 greenlet==0.4.12 gunicorn==19.7.1 @@ -57,7 +57,7 @@ pyotp==2.2.6 PyNaCl==1.2.1 python-dateutil==2.6.1 python-gssapi==0.6.4 -pytz==2017.3 +pytz==2018.3 PyYAML==3.12 redis==2.10.6 requests==2.18.4