diff --git a/apps/assets/api/node.py b/apps/assets/api/node.py
index ff04ee492..471a096b6 100644
--- a/apps/assets/api/node.py
+++ b/apps/assets/api/node.py
@@ -42,13 +42,6 @@ class NodeViewSet(viewsets.ModelViewSet):
permission_classes = (IsOrgAdmin,)
serializer_class = serializers.NodeSerializer
- def get_queryset(self):
- # queryset = super(NodeViewSet, self).get_queryset()
- print("API GET QUWRYSET")
- # print(get_current_org())
- # print(queryset)
- return Node.objects.all()
-
def perform_create(self, serializer):
child_key = Node.root().get_next_child_key()
serializer.validated_data["key"] = child_key
diff --git a/apps/assets/forms/asset.py b/apps/assets/forms/asset.py
index 39ad7713e..8b132b350 100644
--- a/apps/assets/forms/asset.py
+++ b/apps/assets/forms/asset.py
@@ -48,7 +48,7 @@ class AssetCreateForm(OrgModelForm):
'root or other NOPASSWD sudo privilege user existed in asset,'
'If asset is windows or other set any one, more see admin user left menu'
),
- 'platform': _("* required Must set exact system platform, Windows, Linux ..."),
+ # 'platform': _("* required Must set exact system platform, Windows, Linux ..."),
'domain': _("If your have some network not connect with each other, you can set domain")
}
@@ -88,7 +88,7 @@ class AssetUpdateForm(OrgModelForm):
'root or other NOPASSWD sudo privilege user existed in asset,'
'If asset is windows or other set any one, more see admin user left menu'
),
- 'platform': _("* required Must set exact system platform, Windows, Linux ..."),
+ # 'platform': _("* required Must set exact system platform, Windows, Linux ..."),
'domain': _("If your have some network not connect with each other, you can set domain")
}
diff --git a/apps/assets/models/node.py b/apps/assets/models/node.py
index 34becbdb6..27a8e4519 100644
--- a/apps/assets/models/node.py
+++ b/apps/assets/models/node.py
@@ -114,7 +114,7 @@ class Node(OrgModelMixin):
args = []
kwargs = {}
if self.is_default_node():
- args.append(Q(nodes__key__regex=pattern) | Q(nodes__key=None))
+ args.append(Q(nodes__key__regex=pattern) | Q(nodes=None))
else:
kwargs['nodes__key__regex'] = pattern
assets = Asset.objects.filter(*args, **kwargs)
@@ -178,12 +178,15 @@ class Node(OrgModelMixin):
# 如果使用current_org 在set_current_org时会死循环
_current_org = get_current_org()
with transaction.atomic():
- set_current_org(Organization.root())
- org_nodes_roots = cls.objects.filter(key__regex=r'^[0-9]+$')
- org_nodes_roots_keys = org_nodes_roots.values_list('key', flat=True)
- max_value = max([int(k) for k in org_nodes_roots_keys]) if org_nodes_roots_keys else -1
- set_current_org(_current_org)
- root = cls.objects.create(key=str(max_value+1), value=_current_org.name)
+ if _current_org.is_default():
+ key = '0'
+ else:
+ set_current_org(Organization.root())
+ org_nodes_roots = cls.objects.filter(key__regex=r'^[0-9]+$')
+ org_nodes_roots_keys = org_nodes_roots.values_list('key', flat=True)
+ key = max([int(k) for k in org_nodes_roots_keys]) + 1
+ set_current_org(_current_org)
+ root = cls.objects.create(key=key, value=_current_org.name)
return root
@classmethod
diff --git a/apps/assets/models/user.py b/apps/assets/models/user.py
index be7a98ebf..646b7204f 100644
--- a/apps/assets/models/user.py
+++ b/apps/assets/models/user.py
@@ -119,6 +119,8 @@ class SystemUser(AssetUser):
shell = models.CharField(max_length=64, default='/bin/bash', verbose_name=_('Shell'))
login_mode = models.CharField(choices=LOGIN_MODE_CHOICES, default=AUTO_LOGIN, max_length=10, verbose_name=_('Login mode'))
+ cache_key = "__SYSTEM_USER_CACHED_{}"
+
def __str__(self):
return '{0.name}({0.username})'.format(self)
@@ -155,6 +157,24 @@ class SystemUser(AssetUser):
else:
return False
+ def set_cache(self):
+ cache.set(self.cache_key.format(self.id), self, 3600)
+
+ def expire_cache(self):
+ cache.delete(self.cache_key.format(self.id))
+
+ @classmethod
+ def get_system_user_by_id_or_cached(cls, sid):
+ cached = cache.get(cls.cache_key.format(sid))
+ if cached:
+ return cached
+ try:
+ system_user = cls.objects.get(id=sid)
+ system_user.set_cache()
+ return system_user
+ except cls.DoesNotExist:
+ return None
+
class Meta:
ordering = ['name']
unique_together = [('name', 'org_id')]
diff --git a/apps/assets/serializers/node.py b/apps/assets/serializers/node.py
index 0352dfecc..3eca3276f 100644
--- a/apps/assets/serializers/node.py
+++ b/apps/assets/serializers/node.py
@@ -26,7 +26,7 @@ class NodeGrantedSerializer(BulkSerializerMixin, serializers.ModelSerializer):
model = Node
fields = [
'id', 'key', 'name', 'value', 'parent',
- 'assets_granted', 'assets_amount',
+ 'assets_granted', 'assets_amount', 'org_id',
]
@staticmethod
@@ -48,7 +48,10 @@ class NodeSerializer(serializers.ModelSerializer):
class Meta:
model = Node
- fields = ['id', 'key', 'value', 'parent', 'assets_amount', 'is_node']
+ fields = [
+ 'id', 'key', 'value', 'parent', 'assets_amount',
+ 'is_node', 'org_id',
+ ]
list_serializer_class = BulkListSerializer
def validate(self, data):
diff --git a/apps/assets/templates/assets/asset_create.html b/apps/assets/templates/assets/asset_create.html
index 55e233d0d..2a3d62b3d 100644
--- a/apps/assets/templates/assets/asset_create.html
+++ b/apps/assets/templates/assets/asset_create.html
@@ -15,10 +15,10 @@
{% csrf_token %}
{% trans 'Basic' %}
{% bootstrap_field form.hostname layout="horizontal" %}
- {% bootstrap_field form.platform layout="horizontal" %}
{% bootstrap_field form.ip layout="horizontal" %}
{% bootstrap_field form.protocol layout="horizontal" %}
{% bootstrap_field form.port layout="horizontal" %}
+ {% bootstrap_field form.platform layout="horizontal" %}
{% bootstrap_field form.public_ip layout="horizontal" %}
{% bootstrap_field form.domain layout="horizontal" %}
diff --git a/apps/assets/templates/assets/asset_list.html b/apps/assets/templates/assets/asset_list.html
index 23d7fe001..270cc4c4f 100644
--- a/apps/assets/templates/assets/asset_list.html
+++ b/apps/assets/templates/assets/asset_list.html
@@ -406,10 +406,11 @@ function initTree() {
var zNodes = [];
$.get("{% url 'api-assets:node-list' %}", function(data, status){
$.each(data, function (index, value) {
- value["pId"] = value["parent"];
- if (value["key"] === "0") {
- value["open"] = true;
- }
+ if (value["parent"] !== value["id"]){
+ value["pId"] = value["parent"];
+ } else {
+ value["isParent"] = true;
+ }
value["name"] = value["value"] + ' (' + value['assets_amount'] + ')';
value['value'] = value['value'];
});
diff --git a/apps/common/forms.py b/apps/common/forms.py
index a11420498..8667aa128 100644
--- a/apps/common/forms.py
+++ b/apps/common/forms.py
@@ -181,7 +181,7 @@ class SecuritySettingForm(BaseForm):
)
# limit login count
SECURITY_LOGIN_LIMIT_COUNT = forms.IntegerField(
- initial=3, min_value=3,
+ initial=7, min_value=3,
label=_("Limit the number of login failures")
)
# limit login time
diff --git a/apps/jumpserver/settings.py b/apps/jumpserver/settings.py
index 5d60f7a15..ff69c9621 100644
--- a/apps/jumpserver/settings.py
+++ b/apps/jumpserver/settings.py
@@ -411,7 +411,7 @@ TERMINAL_REPLAY_STORAGE = {
DEFAULT_PASSWORD_MIN_LENGTH = 6
-DEFAULT_LOGIN_LIMIT_COUNT = 3
+DEFAULT_LOGIN_LIMIT_COUNT = 7
DEFAULT_LOGIN_LIMIT_TIME = 30
# Django bootstrap3 setting, more see http://django-bootstrap3.readthedocs.io/en/latest/settings.html
diff --git a/apps/orgs/migrations/__init__.py b/apps/orgs/migrations/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/apps/perms/api.py b/apps/perms/api.py
index fd6a64ec4..dd3c6e9c1 100644
--- a/apps/perms/api.py
+++ b/apps/perms/api.py
@@ -15,6 +15,8 @@ from .models import AssetPermission
from .hands import AssetGrantedSerializer, User, UserGroup, Asset, Node, \
NodeGrantedSerializer, SystemUser, NodeSerializer
from . import serializers
+from orgs.utils import set_current_org
+from orgs.models import Organization
class AssetPermissionViewSet(viewsets.ModelViewSet):
@@ -100,6 +102,7 @@ class UserGrantedNodesApi(ListAPIView):
return nodes.keys()
def get_permissions(self):
+ set_current_org(Organization.root())
if self.kwargs.get('pk') is None:
self.permission_classes = (IsValidUser,)
return super().get_permissions()
@@ -129,6 +132,7 @@ class UserGrantedNodesWithAssetsApi(ListAPIView):
return queryset
def get_permissions(self):
+ set_current_org(Organization.root())
if self.kwargs.get('pk') is None:
self.permission_classes = (IsValidUser,)
return super().get_permissions()
@@ -155,6 +159,7 @@ class UserGrantedNodeAssetsApi(ListAPIView):
return assets
def get_permissions(self):
+ set_current_org(Organization.root())
if self.kwargs.get('pk') is None:
self.permission_classes = (IsValidUser,)
return super().get_permissions()
diff --git a/apps/perms/templates/perms/asset_permission_list.html b/apps/perms/templates/perms/asset_permission_list.html
index 5284a3354..36504ef59 100644
--- a/apps/perms/templates/perms/asset_permission_list.html
+++ b/apps/perms/templates/perms/asset_permission_list.html
@@ -240,9 +240,12 @@ function initTree() {
var zNodes = [];
$.get("{% url 'api-assets:node-children-2' %}?assets=1&all=", function(data, status){
$.each(data, function (index, value) {
- value["pId"] = value["parent"];
+ if (value["parent"] !== value["id"]){
+ value["pId"] = value["parent"];
+ } else {
+ value["isParent"] = true;
+ }
value["name"] = value["value"];
- value["open"] = value["key"] === "0";
value["isParent"] = value["is_node"];
value["iconSkin"] = value["is_node"] ? null : 'file';
});
diff --git a/apps/templates/_user_profile.html b/apps/templates/_user_profile.html
index 6717fa771..f4129be9b 100644
--- a/apps/templates/_user_profile.html
+++ b/apps/templates/_user_profile.html
@@ -15,7 +15,7 @@
- {% trans 'Org' %} - {{ CURRENT_ORG.name }}
+ {{ CURRENT_ORG.name }}
diff --git a/apps/terminal/api.py b/apps/terminal/api.py
index 2e7778514..175ccd580 100644
--- a/apps/terminal/api.py
+++ b/apps/terminal/api.py
@@ -4,7 +4,6 @@ from collections import OrderedDict
import logging
import os
import uuid
-import copy
from django.core.cache import cache
from django.shortcuts import get_object_or_404, redirect
@@ -16,12 +15,13 @@ from django.conf import settings
import jms_storage
-from rest_framework import viewsets, serializers
+from rest_framework import viewsets
from rest_framework.views import APIView, Response
from rest_framework.permissions import AllowAny
from rest_framework_bulk import BulkModelViewSet
-from common.utils import get_object_or_none
+from common.utils import get_object_or_none, is_uuid
+from .hands import SystemUser
from .models import Terminal, Status, Session, Task
from .serializers import TerminalSerializer, StatusSerializer, \
SessionSerializer, TaskSerializer, ReplaySerializer
@@ -186,8 +186,13 @@ class SessionViewSet(viewsets.ModelViewSet):
return self.queryset
def perform_create(self, serializer):
- if self.request.user.terminal:
+ if hasattr(self.request.user, 'terminal'):
serializer.validated_data["terminal"] = self.request.user.terminal
+ sid = serializer.validated_data["system_user"]
+ if is_uuid(sid):
+ _system_user = SystemUser.get_system_user_by_id_or_cached(sid)
+ if _system_user:
+ serializer.validated_data["system_user"] = _system_user.name
return super().perform_create(serializer)
diff --git a/apps/terminal/hands.py b/apps/terminal/hands.py
index 71167b09c..6f4c6c78f 100644
--- a/apps/terminal/hands.py
+++ b/apps/terminal/hands.py
@@ -2,3 +2,4 @@
#
from users.models import User
+from assets.models import SystemUser
diff --git a/apps/terminal/templates/terminal/session_list.html b/apps/terminal/templates/terminal/session_list.html
index 6961c99b9..c27b2f8a7 100644
--- a/apps/terminal/templates/terminal/session_list.html
+++ b/apps/terminal/templates/terminal/session_list.html
@@ -58,7 +58,7 @@
diff --git a/apps/terminal/templatetags/terminal_tags.py b/apps/terminal/templatetags/terminal_tags.py
index c5643c67b..e8ba23186 100644
--- a/apps/terminal/templatetags/terminal_tags.py
+++ b/apps/terminal/templatetags/terminal_tags.py
@@ -1,6 +1,7 @@
# ~*~ coding: utf-8 ~*~
from django import template
+
from ..backends import get_multi_command_storage
register = template.Library()
@@ -10,3 +11,4 @@ command_store = get_multi_command_storage()
@register.filter
def get_session_command_amount(session_id):
return command_store.count(session=session_id)
+
diff --git a/utils/2018_07_15_set_win_protocol_to_ssh.sh b/utils/2018_07_15_set_win_protocol_to_ssh.sh
new file mode 100644
index 000000000..6d8596244
--- /dev/null
+++ b/utils/2018_07_15_set_win_protocol_to_ssh.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+#
+
+python ../apps/manage.py shell << EOF
+from assets.models import Asset
+
+Asset.objects.filter(platform__startswith='Win').update(protocol='rdp')
+
+EOF
diff --git a/utils/unblock_all_user.sh b/utils/unblock_all_user.sh
new file mode 100644
index 000000000..6fe4e3356
--- /dev/null
+++ b/utils/unblock_all_user.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+#
+
+python ../apps/manage.py shell << EOF
+from django.core.cache import cache
+
+cache.delete_pattern('_LOGIN_BLOCK_*')
+cache.delete_pattern('_LOGIN_LIMIT_*')
+
+EOF