Unverified Commit 0d2fc27a authored by 老广's avatar 老广 Committed by GitHub

Merge pull request #3420 from jumpserver/bugfix

Bugfix
parents cf65e9bf f4136dec
...@@ -68,7 +68,7 @@ class TreeMixin: ...@@ -68,7 +68,7 @@ class TreeMixin:
@classmethod @classmethod
def refresh_node_assets(cls, t=None): def refresh_node_assets(cls, t=None):
logger.debug("Refresh node tree assets") logger.debug("Refresh node assets")
key = cls.tree_assets_cache_key key = cls.tree_assets_cache_key
ttl = cls.tree_cache_time ttl = cls.tree_cache_time
if not t: if not t:
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
<div class="wrapper wrapper-content"> <div class="wrapper wrapper-content">
<div class="row"> <div class="row">
<div class="col-lg-3" id="split-left" style="padding-left: 3px"> <div class="col-lg-3" id="split-left" style="padding-left: 3px;overflow: auto;max-height: 500px">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div class="ibox-content mailbox-content" style="padding-top: 0;padding-left: 1px"> <div class="ibox-content mailbox-content" style="padding-top: 0;padding-left: 1px">
<div class="file-manager "> <div class="file-manager ">
......
...@@ -32,8 +32,7 @@ ...@@ -32,8 +32,7 @@
} }
</style> </style>
<div class="ibox treebox float-e-margins" style="overflow:auto;">
<div class="ibox float-e-margins">
<div class="ibox-content mailbox-content" style="padding-top: 0;padding-left: 1px"> <div class="ibox-content mailbox-content" style="padding-top: 0;padding-left: 1px">
<div class="file-manager" id="tree-node-id"> <div class="file-manager" id="tree-node-id">
<div id="{% block treeID %}nodeTree{% endblock %}" class="ztree"> <div id="{% block treeID %}nodeTree{% endblock %}" class="ztree">
...@@ -306,6 +305,7 @@ function defaultCallback(action) { ...@@ -306,6 +305,7 @@ function defaultCallback(action) {
$(document).ready(function () { $(document).ready(function () {
$('.treebox').css('height', window.innerHeight - 180);
}) })
.on('click', '.btn-show-current-asset', function(){ .on('click', '.btn-show-current-asset', function(){
hideRMenu(); hideRMenu();
...@@ -322,4 +322,4 @@ $(document).ready(function () { ...@@ -322,4 +322,4 @@ $(document).ready(function () {
location.reload(); location.reload();
}) })
</script> </script>
\ No newline at end of file
...@@ -426,13 +426,15 @@ $(document).ready(function(){ ...@@ -426,13 +426,15 @@ $(document).ready(function(){
function success(data) { function success(data) {
url = setUrlParam(the_url, 'spm', data.spm); url = setUrlParam(the_url, 'spm', data.spm);
requestApi({ requestApi({
url:url, url: url,
method:'DELETE', method: 'DELETE',
success:refreshPage, success: function () {
flash_message:false, var msg = "{% trans 'Asset Deleted.' %}";
swal("{% trans 'Asset Delete' %}", msg, "success");
refreshPage();
},
flash_message: false,
}); });
var msg = "{% trans 'Asset Deleted.' %}";
swal("{% trans 'Asset Delete' %}", msg, "success");
} }
function fail() { function fail() {
var msg = "{% trans 'Asset Deleting failed.' %}"; var msg = "{% trans 'Asset Deleting failed.' %}";
...@@ -440,10 +442,11 @@ $(document).ready(function(){ ...@@ -440,10 +442,11 @@ $(document).ready(function(){
} }
requestApi({ requestApi({
url: "{% url 'api-common:resources-cache' %}", url: "{% url 'api-common:resources-cache' %}",
method:'POST', method: 'POST',
body:JSON.stringify(data), body: JSON.stringify(data),
success:success, success: success,
error:fail error: fail,
flash_message: false
}) })
}) })
} }
......
...@@ -395,6 +395,7 @@ defaults = { ...@@ -395,6 +395,7 @@ defaults = {
'FLOWER_URL': "127.0.0.1:5555", 'FLOWER_URL': "127.0.0.1:5555",
'DEFAULT_ORG_SHOW_ALL_USERS': True, 'DEFAULT_ORG_SHOW_ALL_USERS': True,
'PERIOD_TASK_ENABLED': True, 'PERIOD_TASK_ENABLED': True,
'WINDOWS_SKIP_ALL_MANUAL_PASSWORD': False,
} }
......
...@@ -11,13 +11,6 @@ from .utils.asset_permission import AssetPermissionUtilV2 ...@@ -11,13 +11,6 @@ from .utils.asset_permission import AssetPermissionUtilV2
logger = get_logger(__file__) logger = get_logger(__file__)
permission_m2m_senders = (
AssetPermission.nodes.through,
AssetPermission.assets.through,
AssetPermission.users.through,
AssetPermission.user_groups.through,
)
@receiver([post_save, post_delete], sender=AssetPermission) @receiver([post_save, post_delete], sender=AssetPermission)
@on_transaction_commit @on_transaction_commit
......
...@@ -12,11 +12,14 @@ from django.conf import settings ...@@ -12,11 +12,14 @@ from django.conf import settings
from django.core.mail import send_mail from django.core.mail import send_mail
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from .models import Setting
from .utils import LDAPUtil
from common.permissions import IsOrgAdmin, IsSuperUser from common.permissions import IsOrgAdmin, IsSuperUser
from common.utils import get_logger from common.utils import get_logger
from .serializers import MailTestSerializer, LDAPTestSerializer, LDAPUserSerializer from .models import Setting
from .utils import LDAPUtil
from .serializers import (
MailTestSerializer, LDAPTestSerializer, LDAPUserSerializer,
PublicSettingSerializer,
)
logger = get_logger(__file__) logger = get_logger(__file__)
...@@ -245,3 +248,19 @@ class CommandStorageDeleteAPI(APIView): ...@@ -245,3 +248,19 @@ class CommandStorageDeleteAPI(APIView):
storage_name = str(request.data.get('name')) storage_name = str(request.data.get('name'))
Setting.delete_storage('TERMINAL_COMMAND_STORAGE', storage_name) Setting.delete_storage('TERMINAL_COMMAND_STORAGE', storage_name)
return Response({"msg": _('Delete succeed')}, status=200) return Response({"msg": _('Delete succeed')}, status=200)
class PublicSettingApi(generics.RetrieveAPIView):
permission_classes = ()
serializer_class = PublicSettingSerializer
def get_object(self):
c = settings.CONFIG
instance = {
"data": {
"WINDOWS_SKIP_ALL_MANUAL_PASSWORD": c.WINDOWS_SKIP_ALL_MANUAL_PASSWORD
}
}
return instance
...@@ -28,3 +28,6 @@ class LDAPUserSerializer(serializers.Serializer): ...@@ -28,3 +28,6 @@ class LDAPUserSerializer(serializers.Serializer):
email = serializers.CharField() email = serializers.CharField()
existing = serializers.BooleanField(read_only=True) existing = serializers.BooleanField(read_only=True)
class PublicSettingSerializer(serializers.Serializer):
data = serializers.DictField(read_only=True)
...@@ -15,4 +15,5 @@ urlpatterns = [ ...@@ -15,4 +15,5 @@ urlpatterns = [
path('terminal/replay-storage/delete/', api.ReplayStorageDeleteAPI.as_view(), name='replay-storage-delete'), path('terminal/replay-storage/delete/', api.ReplayStorageDeleteAPI.as_view(), name='replay-storage-delete'),
path('terminal/command-storage/create/', api.CommandStorageCreateAPI.as_view(), name='command-storage-create'), path('terminal/command-storage/create/', api.CommandStorageCreateAPI.as_view(), name='command-storage-create'),
path('terminal/command-storage/delete/', api.CommandStorageDeleteAPI.as_view(), name='command-storage-delete'), path('terminal/command-storage/delete/', api.CommandStorageDeleteAPI.as_view(), name='command-storage-delete'),
path('public/', api.PublicSettingApi.as_view(), name='public-setting'),
] ]
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
from django import forms from django import forms
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.conf import settings
from common.utils import validate_ssh_public_key from common.utils import validate_ssh_public_key
from orgs.mixins.forms import OrgModelForm from orgs.mixins.forms import OrgModelForm
...@@ -21,6 +22,20 @@ class UserCheckOtpCodeForm(forms.Form): ...@@ -21,6 +22,20 @@ class UserCheckOtpCodeForm(forms.Form):
otp_code = forms.CharField(label=_('MFA code'), max_length=6) otp_code = forms.CharField(label=_('MFA code'), max_length=6)
def get_source_choices():
choices_all = dict(User.SOURCE_CHOICES)
choices = [
(User.SOURCE_LOCAL, choices_all[User.SOURCE_LOCAL]),
]
if settings.AUTH_LDAP:
choices.append((User.SOURCE_LDAP, choices_all[User.SOURCE_LDAP]))
if settings.AUTH_OPENID:
choices.append((User.SOURCE_OPENID, choices_all[User.SOURCE_OPENID]))
if settings.AUTH_RADIUS:
choices.append((User.SOURCE_RADIUS, choices_all[User.SOURCE_RADIUS]))
return choices
class UserCreateUpdateFormMixin(OrgModelForm): class UserCreateUpdateFormMixin(OrgModelForm):
role_choices = ((i, n) for i, n in User.ROLE_CHOICES if i != User.ROLE_APP) role_choices = ((i, n) for i, n in User.ROLE_CHOICES if i != User.ROLE_APP)
password = forms.CharField( password = forms.CharField(
...@@ -31,6 +46,10 @@ class UserCreateUpdateFormMixin(OrgModelForm): ...@@ -31,6 +46,10 @@ class UserCreateUpdateFormMixin(OrgModelForm):
choices=role_choices, required=True, choices=role_choices, required=True,
initial=User.ROLE_USER, label=_("Role") initial=User.ROLE_USER, label=_("Role")
) )
source = forms.ChoiceField(
choices=get_source_choices, required=True,
initial=User.SOURCE_LOCAL, label=_("Source")
)
public_key = forms.CharField( public_key = forms.CharField(
label=_('ssh public key'), max_length=5000, required=False, label=_('ssh public key'), max_length=5000, required=False,
widget=forms.Textarea(attrs={'placeholder': _('ssh-rsa AAAA...')}), widget=forms.Textarea(attrs={'placeholder': _('ssh-rsa AAAA...')}),
...@@ -41,7 +60,8 @@ class UserCreateUpdateFormMixin(OrgModelForm): ...@@ -41,7 +60,8 @@ class UserCreateUpdateFormMixin(OrgModelForm):
model = User model = User
fields = [ fields = [
'username', 'name', 'email', 'groups', 'wechat', 'username', 'name', 'email', 'groups', 'wechat',
'phone', 'role', 'date_expired', 'comment', 'otp_level' 'source', 'phone', 'role', 'date_expired',
'comment', 'otp_level'
] ]
widgets = { widgets = {
'otp_level': forms.RadioSelect(), 'otp_level': forms.RadioSelect(),
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
from .v1 import * from .user import *
\ No newline at end of file from .group import *
# -*- coding: utf-8 -*-
#
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers
from common.fields import StringManyToManyField
from common.serializers import AdaptedBulkListSerializer
from orgs.mixins.serializers import BulkOrgResourceModelSerializer
from ..models import User, UserGroup
from .. import utils
__all__ = [
'UserGroupSerializer', 'UserGroupListSerializer',
'UserGroupUpdateMemberSerializer'
]
class UserGroupSerializer(BulkOrgResourceModelSerializer):
users = serializers.PrimaryKeyRelatedField(
required=False, many=True, queryset=User.objects, label=_('User')
)
class Meta:
model = UserGroup
list_serializer_class = AdaptedBulkListSerializer
fields = [
'id', 'name', 'users', 'comment', 'date_created',
'created_by',
]
extra_kwargs = {
'created_by': {'label': _('Created by'), 'read_only': True}
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.set_fields_queryset()
def set_fields_queryset(self):
users_field = self.fields['users']
users_field.child_relation.queryset = utils.get_current_org_members()
def validate_users(self, users):
for user in users:
if user.is_super_auditor:
msg = _('Auditors cannot be join in the user group')
raise serializers.ValidationError(msg)
return users
class UserGroupListSerializer(UserGroupSerializer):
users = StringManyToManyField(many=True, read_only=True)
class UserGroupUpdateMemberSerializer(serializers.ModelSerializer):
users = serializers.PrimaryKeyRelatedField(many=True, queryset=User.objects)
class Meta:
model = UserGroup
fields = ['id', 'users']
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.set_fields_queryset()
def set_fields_queryset(self):
users_field = self.fields['users']
users_field.child_relation.queryset = utils.get_current_org_members()
...@@ -6,19 +6,14 @@ from rest_framework import serializers ...@@ -6,19 +6,14 @@ from rest_framework import serializers
from common.utils import validate_ssh_public_key from common.utils import validate_ssh_public_key
from common.mixins import BulkSerializerMixin from common.mixins import BulkSerializerMixin
from common.fields import StringManyToManyField
from common.serializers import AdaptedBulkListSerializer from common.serializers import AdaptedBulkListSerializer
from common.permissions import CanUpdateDeleteUser from common.permissions import CanUpdateDeleteUser
from orgs.mixins.serializers import BulkOrgResourceModelSerializer
from ..models import User, UserGroup from ..models import User, UserGroup
from .. import utils
__all__ = [ __all__ = [
'UserSerializer', 'UserPKUpdateSerializer', 'UserUpdateGroupSerializer', 'UserSerializer', 'UserPKUpdateSerializer', 'UserUpdateGroupSerializer',
'UserGroupSerializer', 'UserGroupListSerializer', 'ChangeUserPasswordSerializer', 'ResetOTPSerializer',
'UserGroupUpdateMemberSerializer', 'ChangeUserPasswordSerializer',
'ResetOTPSerializer',
] ]
...@@ -49,7 +44,6 @@ class UserSerializer(BulkSerializerMixin, serializers.ModelSerializer): ...@@ -49,7 +44,6 @@ class UserSerializer(BulkSerializerMixin, serializers.ModelSerializer):
'is_valid': {'label': _('Is valid')}, 'is_valid': {'label': _('Is valid')},
'is_expired': {'label': _('Is expired')}, 'is_expired': {'label': _('Is expired')},
'avatar_url': {'label': _('Avatar url')}, 'avatar_url': {'label': _('Avatar url')},
'source': {'read_only': True},
'created_by': {'read_only': True, 'allow_blank': True}, 'created_by': {'read_only': True, 'allow_blank': True},
'can_update': {'read_only': True}, 'can_update': {'read_only': True},
'can_delete': {'read_only': True}, 'can_delete': {'read_only': True},
...@@ -127,58 +121,6 @@ class UserUpdateGroupSerializer(serializers.ModelSerializer): ...@@ -127,58 +121,6 @@ class UserUpdateGroupSerializer(serializers.ModelSerializer):
fields = ['id', 'groups'] fields = ['id', 'groups']
class UserGroupSerializer(BulkOrgResourceModelSerializer):
users = serializers.PrimaryKeyRelatedField(
required=False, many=True, queryset=User.objects, label=_('User')
)
class Meta:
model = UserGroup
list_serializer_class = AdaptedBulkListSerializer
fields = [
'id', 'name', 'users', 'comment', 'date_created',
'created_by',
]
extra_kwargs = {
'created_by': {'label': _('Created by'), 'read_only': True}
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.set_fields_queryset()
def set_fields_queryset(self):
users_field = self.fields['users']
users_field.child_relation.queryset = utils.get_current_org_members()
def validate_users(self, users):
for user in users:
if user.is_super_auditor:
msg = _('Auditors cannot be join in the user group')
raise serializers.ValidationError(msg)
return users
class UserGroupListSerializer(UserGroupSerializer):
users = StringManyToManyField(many=True, read_only=True)
class UserGroupUpdateMemberSerializer(serializers.ModelSerializer):
users = serializers.PrimaryKeyRelatedField(many=True, queryset=User.objects)
class Meta:
model = UserGroup
fields = ['id', 'users']
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.set_fields_queryset()
def set_fields_queryset(self):
users_field = self.fields['users']
users_field.child_relation.queryset = utils.get_current_org_members()
class ChangeUserPasswordSerializer(serializers.ModelSerializer): class ChangeUserPasswordSerializer(serializers.ModelSerializer):
class Meta: class Meta:
......
...@@ -2,11 +2,11 @@ ...@@ -2,11 +2,11 @@
# #
from django.dispatch import receiver from django.dispatch import receiver
# from django.db.models.signals import post_save from django.db.models.signals import post_save, m2m_changed
from common.utils import get_logger from common.utils import get_logger
from .signals import post_user_create from .signals import post_user_create
# from .models import User from .models import User
logger = get_logger(__file__) logger = get_logger(__file__)
...@@ -28,3 +28,14 @@ def on_user_create(sender, user=None, **kwargs): ...@@ -28,3 +28,14 @@ def on_user_create(sender, user=None, **kwargs):
logger.info(" - Sending welcome mail ...".format(user.name)) logger.info(" - Sending welcome mail ...".format(user.name))
if user.email: if user.email:
send_user_created_mail(user) send_user_created_mail(user)
@receiver(m2m_changed, sender=User.groups.through)
def on_user_groups_change(sender, instance=None, action='', **kwargs):
"""
资产节点发生变化时,刷新节点
"""
if action.startswith('post'):
logger.debug("User group member change signal recv: {}".format(instance))
from perms.utils import AssetPermissionUtilV2
AssetPermissionUtilV2.expire_all_user_tree_cache()
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
<h3>{% trans 'Auth' %}</h3> <h3>{% trans 'Auth' %}</h3>
{% block password %}{% endblock %} {% block password %}{% endblock %}
{% bootstrap_field form.otp_level layout="horizontal" %} {% bootstrap_field form.otp_level layout="horizontal" %}
{% bootstrap_field form.source layout="horizontal" %}
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
<h3>{% trans 'Security and Role' %}</h3> <h3>{% trans 'Security and Role' %}</h3>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment