mirror of https://github.com/jumpserver/jumpserver
commit
09fbd3a5ab
|
@ -74,7 +74,7 @@ class AssetViewSet(IDInFilterMixin, LabelFilter, BulkModelViewSet):
|
||||||
.select_related('admin_user')
|
.select_related('admin_user')
|
||||||
self.filter_admin_user_id()
|
self.filter_admin_user_id()
|
||||||
self.filter_node()
|
self.filter_node()
|
||||||
return self.queryset
|
return self.queryset.distinct()
|
||||||
|
|
||||||
|
|
||||||
class AssetListUpdateApi(IDInFilterMixin, ListBulkCreateUpdateDestroyAPIView):
|
class AssetListUpdateApi(IDInFilterMixin, ListBulkCreateUpdateDestroyAPIView):
|
||||||
|
|
|
@ -26,7 +26,7 @@ class CommandFilterRuleViewSet(BulkModelViewSet):
|
||||||
fpk = self.kwargs.get('filter_pk')
|
fpk = self.kwargs.get('filter_pk')
|
||||||
if not fpk:
|
if not fpk:
|
||||||
return CommandFilterRule.objects.none()
|
return CommandFilterRule.objects.none()
|
||||||
group = get_object_or_404(CommandFilter, pk=fpk)
|
cmd_filter = get_object_or_404(CommandFilter, pk=fpk)
|
||||||
return group.rules.all().order_by('priority')
|
return cmd_filter.rules.all()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -150,7 +150,7 @@ class SystemUserForm(OrgModelForm, PasswordAndKeyAuthForm):
|
||||||
'name': '* required',
|
'name': '* required',
|
||||||
'username': '* required',
|
'username': '* required',
|
||||||
'auto_push': _('Auto push system user to asset'),
|
'auto_push': _('Auto push system user to asset'),
|
||||||
'priority': _('High level will be using login asset as default, '
|
'priority': _('1-100, High level will be using login asset as default, '
|
||||||
'if user was granted more than 2 system user'),
|
'if user was granted more than 2 system user'),
|
||||||
'login_mode': _('If you choose manual login mode, you do not '
|
'login_mode': _('If you choose manual login mode, you do not '
|
||||||
'need to fill in the username and password.')
|
'need to fill in the username and password.')
|
||||||
|
|
|
@ -34,7 +34,8 @@ def default_cluster():
|
||||||
def default_node():
|
def default_node():
|
||||||
try:
|
try:
|
||||||
from .node import Node
|
from .node import Node
|
||||||
return Node.root()
|
root = Node.root()
|
||||||
|
return root
|
||||||
except:
|
except:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ class CommandFilterRule(OrgModelMixin):
|
||||||
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
|
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
|
||||||
filter = models.ForeignKey('CommandFilter', on_delete=models.CASCADE, verbose_name=_("Filter"), related_name='rules')
|
filter = models.ForeignKey('CommandFilter', on_delete=models.CASCADE, verbose_name=_("Filter"), related_name='rules')
|
||||||
type = models.CharField(max_length=16, default=TYPE_COMMAND, choices=TYPE_CHOICES, verbose_name=_("Type"))
|
type = models.CharField(max_length=16, default=TYPE_COMMAND, choices=TYPE_CHOICES, verbose_name=_("Type"))
|
||||||
priority = models.IntegerField(default=50, verbose_name=_("Priority"), help_text=_("1-100, the lower will be match first"),
|
priority = models.IntegerField(default=50, verbose_name=_("Priority"), help_text=_("1-100, the higher will be match first"),
|
||||||
validators=[MinValueValidator(1), MaxValueValidator(100)])
|
validators=[MinValueValidator(1), MaxValueValidator(100)])
|
||||||
content = models.TextField(max_length=1024, verbose_name=_("Content"), help_text=_("One line one command"))
|
content = models.TextField(max_length=1024, verbose_name=_("Content"), help_text=_("One line one command"))
|
||||||
action = models.IntegerField(default=ACTION_DENY, choices=ACTION_CHOICES, verbose_name=_("Action"))
|
action = models.IntegerField(default=ACTION_DENY, choices=ACTION_CHOICES, verbose_name=_("Action"))
|
||||||
|
@ -54,7 +54,7 @@ class CommandFilterRule(OrgModelMixin):
|
||||||
created_by = models.CharField(max_length=128, blank=True, default='', verbose_name=_('Created by'))
|
created_by = models.CharField(max_length=128, blank=True, default='', verbose_name=_('Created by'))
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ('priority', 'action')
|
ordering = ('-priority', 'action')
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return '{} % {}'.format(self.type, self.content)
|
return '{} % {}'.format(self.type, self.content)
|
||||||
|
|
|
@ -31,6 +31,8 @@ class Node(OrgModelMixin):
|
||||||
return self.full_value
|
return self.full_value
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
|
if not other:
|
||||||
|
return False
|
||||||
return self.key == other.key
|
return self.key == other.key
|
||||||
|
|
||||||
def __gt__(self, other):
|
def __gt__(self, other):
|
||||||
|
@ -136,7 +138,7 @@ class Node(OrgModelMixin):
|
||||||
args.append(Q(nodes__key__regex=pattern) | Q(nodes=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).distinct()
|
||||||
return assets
|
return assets
|
||||||
|
|
||||||
def get_all_valid_assets(self):
|
def get_all_valid_assets(self):
|
||||||
|
@ -201,13 +203,16 @@ 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():
|
||||||
if _current_org.is_default():
|
if _current_org.is_root():
|
||||||
key = '0'
|
key = '0'
|
||||||
|
elif _current_org.is_default():
|
||||||
|
key = '1'
|
||||||
else:
|
else:
|
||||||
set_current_org(Organization.root())
|
set_current_org(Organization.root())
|
||||||
org_nodes_roots = cls.objects.filter(key__regex=r'^[0-9]+$')
|
org_nodes_roots = cls.objects.filter(key__regex=r'^[0-9]+$')
|
||||||
org_nodes_roots_keys = org_nodes_roots.values_list('key', flat=True) or [0]
|
org_nodes_roots_keys = org_nodes_roots.values_list('key', flat=True) or ['1']
|
||||||
key = str(max([int(k) for k in org_nodes_roots_keys]) + 1)
|
key = max([int(k) for k in org_nodes_roots_keys])
|
||||||
|
key = str(key + 1) if key != 0 else '2'
|
||||||
set_current_org(_current_org)
|
set_current_org(_current_org)
|
||||||
root = cls.objects.create(key=key, value=_current_org.name)
|
root = cls.objects.create(key=key, value=_current_org.name)
|
||||||
return root
|
return root
|
||||||
|
@ -223,7 +228,7 @@ class Node(OrgModelMixin):
|
||||||
@classmethod
|
@classmethod
|
||||||
def default_node(cls):
|
def default_node(cls):
|
||||||
defaults = {'value': 'Default'}
|
defaults = {'value': 'Default'}
|
||||||
return cls.objects.get_or_create(defaults=defaults, key='0')
|
return cls.objects.get_or_create(defaults=defaults, key='1')
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_tree_name_ref(cls):
|
def get_tree_name_ref(cls):
|
||||||
|
|
|
@ -7,6 +7,7 @@ import logging
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
from django.core.validators import MinValueValidator, MaxValueValidator
|
||||||
|
|
||||||
from common.utils import get_signer
|
from common.utils import get_signer
|
||||||
from ..const import SYSTEM_USER_CONN_CACHE_KEY
|
from ..const import SYSTEM_USER_CONN_CACHE_KEY
|
||||||
|
@ -111,7 +112,8 @@ class SystemUser(AssetUser):
|
||||||
|
|
||||||
nodes = models.ManyToManyField('assets.Node', blank=True, verbose_name=_("Nodes"))
|
nodes = models.ManyToManyField('assets.Node', blank=True, verbose_name=_("Nodes"))
|
||||||
assets = models.ManyToManyField('assets.Asset', blank=True, verbose_name=_("Assets"))
|
assets = models.ManyToManyField('assets.Asset', blank=True, verbose_name=_("Assets"))
|
||||||
priority = models.IntegerField(default=10, verbose_name=_("Priority"))
|
priority = models.IntegerField(default=20, verbose_name=_("Priority"),
|
||||||
|
validators=[MinValueValidator(1), MaxValueValidator(100)])
|
||||||
protocol = models.CharField(max_length=16, choices=PROTOCOL_CHOICES, default='ssh', verbose_name=_('Protocol'))
|
protocol = models.CharField(max_length=16, choices=PROTOCOL_CHOICES, default='ssh', verbose_name=_('Protocol'))
|
||||||
auto_push = models.BooleanField(default=True, verbose_name=_('Auto push'))
|
auto_push = models.BooleanField(default=True, verbose_name=_('Auto push'))
|
||||||
sudo = models.TextField(default='/bin/whoami', verbose_name=_('Sudo'))
|
sudo = models.TextField(default='/bin/whoami', verbose_name=_('Sudo'))
|
||||||
|
@ -168,7 +170,7 @@ class SystemUser(AssetUser):
|
||||||
from .cmd_filter import CommandFilterRule
|
from .cmd_filter import CommandFilterRule
|
||||||
rules = CommandFilterRule.objects.filter(
|
rules = CommandFilterRule.objects.filter(
|
||||||
filter__in=self.cmd_filters.all()
|
filter__in=self.cmd_filters.all()
|
||||||
).order_by('priority').distinct()
|
).distinct()
|
||||||
return rules
|
return rules
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
|
@ -69,6 +69,10 @@
|
||||||
<td>{% trans 'Port' %}:</td>
|
<td>{% trans 'Port' %}:</td>
|
||||||
<td><b>{{ asset.port }}</b></td>
|
<td><b>{{ asset.port }}</b></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{% trans 'Protocol' %}:</td>
|
||||||
|
<td><b>{{ asset.protocol }}</b></td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>{% trans 'Admin user' %}:</td>
|
<td>{% trans 'Admin user' %}:</td>
|
||||||
<td><b>{{ asset.admin_user }}</b></td>
|
<td><b>{{ asset.admin_user }}</b></td>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<div class="alert alert-info help-message">
|
<div class="alert alert-info help-message">
|
||||||
{% trans 'System user bound some command filter, each command filter has some rules,'%}
|
{% trans 'System user bound some command filter, each command filter has some rules,'%}
|
||||||
{% trans 'When user login asset with this system user, then run a command,' %}
|
{% trans 'When user login asset with this system user, then run a command,' %}
|
||||||
{% trans 'The command will be filter by rules, higher priority(lower number) rule run first,' %}
|
{% trans 'The command will be filter by rules, higher priority rule run first,' %}
|
||||||
{% trans 'When a rule matched, if rule action is allow, then allow command execute,' %}
|
{% trans 'When a rule matched, if rule action is allow, then allow command execute,' %}
|
||||||
{% trans 'else if action is deny, then command with be deny,' %}
|
{% trans 'else if action is deny, then command with be deny,' %}
|
||||||
{% trans 'else match next rule, if none matched, allowed' %}
|
{% trans 'else match next rule, if none matched, allowed' %}
|
||||||
|
|
|
@ -45,10 +45,7 @@ class AssetListView(AdminUserRequiredMixin, TemplateView):
|
||||||
template_name = 'assets/asset_list.html'
|
template_name = 'assets/asset_list.html'
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
if current_org.is_default():
|
Node.root()
|
||||||
Node.default_node()
|
|
||||||
else:
|
|
||||||
Node.root()
|
|
||||||
context = {
|
context = {
|
||||||
'app': _('Assets'),
|
'app': _('Assets'),
|
||||||
'action': _('Asset list'),
|
'action': _('Asset list'),
|
||||||
|
|
|
@ -18,6 +18,9 @@ class BaseForm(forms.Form):
|
||||||
db_value = getattr(common_settings, name)
|
db_value = getattr(common_settings, name)
|
||||||
django_value = getattr(settings, name) if hasattr(settings, name) else None
|
django_value = getattr(settings, name) if hasattr(settings, name) else None
|
||||||
|
|
||||||
|
if db_value is None and django_value is None:
|
||||||
|
continue
|
||||||
|
|
||||||
if db_value is False or db_value:
|
if db_value is False or db_value:
|
||||||
if isinstance(db_value, dict):
|
if isinstance(db_value, dict):
|
||||||
db_value = json.dumps(db_value)
|
db_value = json.dumps(db_value)
|
||||||
|
|
|
@ -106,3 +106,8 @@ def to_dict(data):
|
||||||
def sort(data):
|
def sort(data):
|
||||||
print(data)
|
print(data)
|
||||||
return sorted(data)
|
return sorted(data)
|
||||||
|
|
||||||
|
|
||||||
|
@register.filter
|
||||||
|
def subtract(value, arg):
|
||||||
|
return value - arg
|
||||||
|
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
@ -4,7 +4,6 @@
|
||||||
from werkzeug.local import Local
|
from werkzeug.local import Local
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.db.models import Q
|
|
||||||
from django.shortcuts import redirect
|
from django.shortcuts import redirect
|
||||||
from django.forms import ModelForm
|
from django.forms import ModelForm
|
||||||
from django.http.response import HttpResponseForbidden
|
from django.http.response import HttpResponseForbidden
|
||||||
|
|
|
@ -96,7 +96,7 @@ class UserGrantedNodesApi(ListAPIView):
|
||||||
"""
|
"""
|
||||||
查询用户授权的所有节点的API, 如果是超级用户或者是 app,切换到root org
|
查询用户授权的所有节点的API, 如果是超级用户或者是 app,切换到root org
|
||||||
"""
|
"""
|
||||||
permission_classes = (IsOrgAdmin,)
|
permission_classes = (IsOrgAdminOrAppUser,)
|
||||||
serializer_class = NodeSerializer
|
serializer_class = NodeSerializer
|
||||||
|
|
||||||
def change_org_if_need(self):
|
def change_org_if_need(self):
|
||||||
|
|
|
@ -145,7 +145,14 @@ function activeNav() {
|
||||||
var resource = url_array[2];
|
var resource = url_array[2];
|
||||||
if (app === ''){
|
if (app === ''){
|
||||||
$('#index').addClass('active');
|
$('#index').addClass('active');
|
||||||
} else {
|
}
|
||||||
|
else if (app === 'xpack') {
|
||||||
|
var item = url_array[3];
|
||||||
|
$("#" + app).addClass('active');
|
||||||
|
$('#' + app + ' #' + resource).addClass('active');
|
||||||
|
$('#' + app + ' #' + resource + ' #' + item + ' a').css('color', '#ffffff');
|
||||||
|
}
|
||||||
|
else {
|
||||||
$("#" + app).addClass('active');
|
$("#" + app).addClass('active');
|
||||||
$('#' + app + ' #' + resource).addClass('active');
|
$('#' + app + ' #' + resource).addClass('active');
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,7 +95,17 @@
|
||||||
</a>
|
</a>
|
||||||
<ul class="nav nav-second-level">
|
<ul class="nav nav-second-level">
|
||||||
{% for plugin in XPACK_PLUGINS %}
|
{% for plugin in XPACK_PLUGINS %}
|
||||||
<li id="{{ plugin.name }}"><a href="{{ plugin.endpoint }}">{% trans plugin.verbose_name %}</a></li>
|
{% ifequal plugin.name 'cloud'%}
|
||||||
|
<li id="{{ plugin.name }}">
|
||||||
|
<a href="#"><span class="nav-label">{% trans plugin.verbose_name %}</span><span class="fa arrow"></span></a>
|
||||||
|
<ul class="nav nav-third-level">
|
||||||
|
<li id="account"><a href="{% url 'xpack:cloud:account-list' %}">{% trans 'Account list' %}</a></li>
|
||||||
|
<li id="sync-instance-task"><a href="{% url 'xpack:cloud:sync-instance-task-list' %}">{% trans 'Sync instance' %}</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
{% else %}
|
||||||
|
<li id="{{ plugin.name }}"><a href="{{ plugin.endpoint }}">{% trans plugin.verbose_name %}</a></li>
|
||||||
|
{% endifequal %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -9,8 +9,13 @@
|
||||||
<i class="fa fa-user" style="width: 14px"></i> <span class="nav-label">{% trans 'Profile' %}</span><span class="label label-info pull-right"></span>
|
<i class="fa fa-user" style="width: 14px"></i> <span class="nav-label">{% trans 'Profile' %}</span><span class="label label-info pull-right"></span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li >
|
<li>
|
||||||
<a href="{% url 'terminal:web-terminal' %}" target="_blank"><i class="fa fa-window-maximize" style="width: 14px"></i>
|
<a href="{% url 'terminal:web-terminal' %}" target="_blank"><i class="fa fa-window-maximize" style="width: 14px"></i>
|
||||||
<span class="nav-label">{% trans 'Web terminal' %}</span>
|
<span class="nav-label">{% trans 'Web terminal' %}</span>
|
||||||
</a>
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{% url 'terminal:web-sftp' %}" target="_blank"><i class="fa fa-file" style="width: 14px"></i>
|
||||||
|
<span class="nav-label">{% trans 'File manager' %}</span>
|
||||||
|
</a>
|
||||||
</li>
|
</li>
|
|
@ -72,3 +72,5 @@ vine==1.1.4
|
||||||
drf-yasg==1.9.1
|
drf-yasg==1.9.1
|
||||||
Werkzeug==0.14.1
|
Werkzeug==0.14.1
|
||||||
drf-nested-routers==0.90.2
|
drf-nested-routers==0.90.2
|
||||||
|
aliyun-python-sdk-core-v3==2.9.1
|
||||||
|
aliyun-python-sdk-ecs==4.10.1
|
||||||
|
|
Loading…
Reference in New Issue