Merge branch 'org' into tmp_org

pull/1644/head
ibuler 2018-07-27 16:16:29 +08:00
commit 9166a26f80
19 changed files with 88 additions and 33 deletions

View File

@ -42,13 +42,6 @@ class NodeViewSet(viewsets.ModelViewSet):
permission_classes = (IsOrgAdmin,) permission_classes = (IsOrgAdmin,)
serializer_class = serializers.NodeSerializer 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): def perform_create(self, serializer):
child_key = Node.root().get_next_child_key() child_key = Node.root().get_next_child_key()
serializer.validated_data["key"] = child_key serializer.validated_data["key"] = child_key

View File

@ -48,7 +48,7 @@ class AssetCreateForm(OrgModelForm):
'root or other NOPASSWD sudo privilege user existed in asset,' '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' '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") '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,' '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' '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") 'domain': _("If your have some network not connect with each other, you can set domain")
} }

View File

@ -114,7 +114,7 @@ class Node(OrgModelMixin):
args = [] args = []
kwargs = {} kwargs = {}
if self.is_default_node(): 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: else:
kwargs['nodes__key__regex'] = pattern kwargs['nodes__key__regex'] = pattern
assets = Asset.objects.filter(*args, **kwargs) assets = Asset.objects.filter(*args, **kwargs)
@ -178,12 +178,15 @@ class Node(OrgModelMixin):
# 如果使用current_org 在set_current_org时会死循环 # 如果使用current_org 在set_current_org时会死循环
_current_org = get_current_org() _current_org = get_current_org()
with transaction.atomic(): with transaction.atomic():
set_current_org(Organization.root()) if _current_org.is_default():
org_nodes_roots = cls.objects.filter(key__regex=r'^[0-9]+$') key = '0'
org_nodes_roots_keys = org_nodes_roots.values_list('key', flat=True) else:
max_value = max([int(k) for k in org_nodes_roots_keys]) if org_nodes_roots_keys else -1 set_current_org(Organization.root())
set_current_org(_current_org) org_nodes_roots = cls.objects.filter(key__regex=r'^[0-9]+$')
root = cls.objects.create(key=str(max_value+1), value=_current_org.name) 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 return root
@classmethod @classmethod

View File

@ -119,6 +119,8 @@ class SystemUser(AssetUser):
shell = models.CharField(max_length=64, default='/bin/bash', verbose_name=_('Shell')) 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')) 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): def __str__(self):
return '{0.name}({0.username})'.format(self) return '{0.name}({0.username})'.format(self)
@ -155,6 +157,24 @@ class SystemUser(AssetUser):
else: else:
return False 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: class Meta:
ordering = ['name'] ordering = ['name']
unique_together = [('name', 'org_id')] unique_together = [('name', 'org_id')]

View File

@ -26,7 +26,7 @@ class NodeGrantedSerializer(BulkSerializerMixin, serializers.ModelSerializer):
model = Node model = Node
fields = [ fields = [
'id', 'key', 'name', 'value', 'parent', 'id', 'key', 'name', 'value', 'parent',
'assets_granted', 'assets_amount', 'assets_granted', 'assets_amount', 'org_id',
] ]
@staticmethod @staticmethod
@ -48,7 +48,10 @@ class NodeSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Node 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 list_serializer_class = BulkListSerializer
def validate(self, data): def validate(self, data):

View File

@ -15,10 +15,10 @@
{% csrf_token %} {% csrf_token %}
<h3>{% trans 'Basic' %}</h3> <h3>{% trans 'Basic' %}</h3>
{% bootstrap_field form.hostname layout="horizontal" %} {% bootstrap_field form.hostname layout="horizontal" %}
{% bootstrap_field form.platform layout="horizontal" %}
{% bootstrap_field form.ip layout="horizontal" %} {% bootstrap_field form.ip layout="horizontal" %}
{% bootstrap_field form.protocol layout="horizontal" %} {% bootstrap_field form.protocol layout="horizontal" %}
{% bootstrap_field form.port layout="horizontal" %} {% bootstrap_field form.port layout="horizontal" %}
{% bootstrap_field form.platform layout="horizontal" %}
{% bootstrap_field form.public_ip layout="horizontal" %} {% bootstrap_field form.public_ip layout="horizontal" %}
{% bootstrap_field form.domain layout="horizontal" %} {% bootstrap_field form.domain layout="horizontal" %}

View File

@ -406,10 +406,11 @@ function initTree() {
var zNodes = []; var zNodes = [];
$.get("{% url 'api-assets:node-list' %}", function(data, status){ $.get("{% url 'api-assets:node-list' %}", function(data, status){
$.each(data, function (index, value) { $.each(data, function (index, value) {
value["pId"] = value["parent"]; if (value["parent"] !== value["id"]){
if (value["key"] === "0") { value["pId"] = value["parent"];
value["open"] = true; } else {
} value["isParent"] = true;
}
value["name"] = value["value"] + ' (' + value['assets_amount'] + ')'; value["name"] = value["value"] + ' (' + value['assets_amount'] + ')';
value['value'] = value['value']; value['value'] = value['value'];
}); });

View File

@ -181,7 +181,7 @@ class SecuritySettingForm(BaseForm):
) )
# limit login count # limit login count
SECURITY_LOGIN_LIMIT_COUNT = forms.IntegerField( SECURITY_LOGIN_LIMIT_COUNT = forms.IntegerField(
initial=3, min_value=3, initial=7, min_value=3,
label=_("Limit the number of login failures") label=_("Limit the number of login failures")
) )
# limit login time # limit login time

View File

@ -411,7 +411,7 @@ TERMINAL_REPLAY_STORAGE = {
DEFAULT_PASSWORD_MIN_LENGTH = 6 DEFAULT_PASSWORD_MIN_LENGTH = 6
DEFAULT_LOGIN_LIMIT_COUNT = 3 DEFAULT_LOGIN_LIMIT_COUNT = 7
DEFAULT_LOGIN_LIMIT_TIME = 30 DEFAULT_LOGIN_LIMIT_TIME = 30
# Django bootstrap3 setting, more see http://django-bootstrap3.readthedocs.io/en/latest/settings.html # Django bootstrap3 setting, more see http://django-bootstrap3.readthedocs.io/en/latest/settings.html

View File

View File

@ -15,6 +15,8 @@ from .models import AssetPermission
from .hands import AssetGrantedSerializer, User, UserGroup, Asset, Node, \ from .hands import AssetGrantedSerializer, User, UserGroup, Asset, Node, \
NodeGrantedSerializer, SystemUser, NodeSerializer NodeGrantedSerializer, SystemUser, NodeSerializer
from . import serializers from . import serializers
from orgs.utils import set_current_org
from orgs.models import Organization
class AssetPermissionViewSet(viewsets.ModelViewSet): class AssetPermissionViewSet(viewsets.ModelViewSet):
@ -100,6 +102,7 @@ class UserGrantedNodesApi(ListAPIView):
return nodes.keys() return nodes.keys()
def get_permissions(self): def get_permissions(self):
set_current_org(Organization.root())
if self.kwargs.get('pk') is None: if self.kwargs.get('pk') is None:
self.permission_classes = (IsValidUser,) self.permission_classes = (IsValidUser,)
return super().get_permissions() return super().get_permissions()
@ -129,6 +132,7 @@ class UserGrantedNodesWithAssetsApi(ListAPIView):
return queryset return queryset
def get_permissions(self): def get_permissions(self):
set_current_org(Organization.root())
if self.kwargs.get('pk') is None: if self.kwargs.get('pk') is None:
self.permission_classes = (IsValidUser,) self.permission_classes = (IsValidUser,)
return super().get_permissions() return super().get_permissions()
@ -155,6 +159,7 @@ class UserGrantedNodeAssetsApi(ListAPIView):
return assets return assets
def get_permissions(self): def get_permissions(self):
set_current_org(Organization.root())
if self.kwargs.get('pk') is None: if self.kwargs.get('pk') is None:
self.permission_classes = (IsValidUser,) self.permission_classes = (IsValidUser,)
return super().get_permissions() return super().get_permissions()

View File

@ -240,9 +240,12 @@ function initTree() {
var zNodes = []; var zNodes = [];
$.get("{% url 'api-assets:node-children-2' %}?assets=1&all=", function(data, status){ $.get("{% url 'api-assets:node-children-2' %}?assets=1&all=", function(data, status){
$.each(data, function (index, value) { $.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["name"] = value["value"];
value["open"] = value["key"] === "0";
value["isParent"] = value["is_node"]; value["isParent"] = value["is_node"];
value["iconSkin"] = value["is_node"] ? null : 'file'; value["iconSkin"] = value["is_node"] ? null : 'file';
}); });

View File

@ -15,7 +15,7 @@
<a class="dropdown-toggle" data-toggle="dropdown" aria-expanded="false" style="display: block; background-color: transparent; color: #8095a8; padding: 14px 20px 14px 25px"> <a class="dropdown-toggle" data-toggle="dropdown" aria-expanded="false" style="display: block; background-color: transparent; color: #8095a8; padding: 14px 20px 14px 25px">
<i class="fa fa-bookmark" style="width: 14px; "></i> <i class="fa fa-bookmark" style="width: 14px; "></i>
<span class="nav-label" style="padding-left: 7px"> <span class="nav-label" style="padding-left: 7px">
{% trans 'Org' %} - {{ CURRENT_ORG.name }} {{ CURRENT_ORG.name }}
</span> </span>
<span class="fa fa-sort-desc pull-right"></span> <span class="fa fa-sort-desc pull-right"></span>
</a> </a>

View File

@ -4,7 +4,6 @@ from collections import OrderedDict
import logging import logging
import os import os
import uuid import uuid
import copy
from django.core.cache import cache from django.core.cache import cache
from django.shortcuts import get_object_or_404, redirect from django.shortcuts import get_object_or_404, redirect
@ -16,12 +15,13 @@ from django.conf import settings
import jms_storage import jms_storage
from rest_framework import viewsets, serializers from rest_framework import viewsets
from rest_framework.views import APIView, Response from rest_framework.views import APIView, Response
from rest_framework.permissions import AllowAny from rest_framework.permissions import AllowAny
from rest_framework_bulk import BulkModelViewSet 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 .models import Terminal, Status, Session, Task
from .serializers import TerminalSerializer, StatusSerializer, \ from .serializers import TerminalSerializer, StatusSerializer, \
SessionSerializer, TaskSerializer, ReplaySerializer SessionSerializer, TaskSerializer, ReplaySerializer
@ -186,8 +186,13 @@ class SessionViewSet(viewsets.ModelViewSet):
return self.queryset return self.queryset
def perform_create(self, serializer): def perform_create(self, serializer):
if self.request.user.terminal: if hasattr(self.request.user, 'terminal'):
serializer.validated_data["terminal"] = 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) return super().perform_create(serializer)

View File

@ -2,3 +2,4 @@
# #
from users.models import User from users.models import User
from assets.models import SystemUser

View File

@ -58,7 +58,7 @@
<div class="input-group"> <div class="input-group">
<div class="input-group-btn"> <div class="input-group-btn">
<button id='search_btn' type="submit" class="btn btn-sm btn-primary"> <button id='search_btn' type="submit" class="btn btn-sm btn-primary">
搜索 {% trans 'Search' %}
</button> </button>
</div> </div>
</div> </div>

View File

@ -1,6 +1,7 @@
# ~*~ coding: utf-8 ~*~ # ~*~ coding: utf-8 ~*~
from django import template from django import template
from ..backends import get_multi_command_storage from ..backends import get_multi_command_storage
register = template.Library() register = template.Library()
@ -10,3 +11,4 @@ command_store = get_multi_command_storage()
@register.filter @register.filter
def get_session_command_amount(session_id): def get_session_command_amount(session_id):
return command_store.count(session=session_id) return command_store.count(session=session_id)

View File

@ -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

10
utils/unblock_all_user.sh Normal file
View File

@ -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