mirror of https://github.com/jumpserver/jumpserver
Merge branch 'org' into tmp_org
commit
9166a26f80
|
@ -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
|
||||||
|
|
|
@ -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")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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')]
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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" %}
|
||||||
|
|
||||||
|
|
|
@ -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'];
|
||||||
});
|
});
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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';
|
||||||
});
|
});
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,3 +2,4 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
from users.models import User
|
from users.models import User
|
||||||
|
from assets.models import SystemUser
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue