Commit c31b56dd authored by BaiJiangJie's avatar BaiJiangJie

[Update] Merge local branch dev to dev_ldap2

parents 0a08ba3b 0d2fc27a
...@@ -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();
......
...@@ -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.' %}"; var msg = "{% trans 'Asset Deleted.' %}";
swal("{% trans 'Asset Delete' %}", msg, "success"); swal("{% trans 'Asset Delete' %}", msg, "success");
refreshPage();
},
flash_message: false,
});
} }
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
......
...@@ -21,7 +21,10 @@ from .utils import ( ...@@ -21,7 +21,10 @@ from .utils import (
from .tasks import sync_ldap_user_task from .tasks import sync_ldap_user_task
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 .serializers import (
MailTestSerializer, LDAPTestSerializer, LDAPUserSerializer,
PublicSettingSerializer,
)
from users.models import User from users.models import User
...@@ -29,7 +32,7 @@ logger = get_logger(__file__) ...@@ -29,7 +32,7 @@ logger = get_logger(__file__)
class MailTestingAPI(APIView): class MailTestingAPI(APIView):
permission_classes = (IsOrgAdmin,) permission_classes = (IsSuperUser,)
serializer_class = MailTestSerializer serializer_class = MailTestSerializer
success_message = _("Test mail sent to {}, please check") success_message = _("Test mail sent to {}, please check")
...@@ -68,7 +71,7 @@ class MailTestingAPI(APIView): ...@@ -68,7 +71,7 @@ class MailTestingAPI(APIView):
class LDAPTestingAPI(APIView): class LDAPTestingAPI(APIView):
permission_classes = (IsOrgAdmin,) permission_classes = (IsSuperUser,)
serializer_class = LDAPTestSerializer serializer_class = LDAPTestSerializer
success_message = _("Test ldap success") success_message = _("Test ldap success")
...@@ -114,7 +117,7 @@ class LDAPTestingAPI(APIView): ...@@ -114,7 +117,7 @@ class LDAPTestingAPI(APIView):
class LDAPUserListApi(generics.ListAPIView): class LDAPUserListApi(generics.ListAPIView):
permission_classes = (IsOrgAdmin,) permission_classes = (IsSuperUser,)
serializer_class = LDAPUserSerializer serializer_class = LDAPUserSerializer
def get_queryset_from_cache(self): def get_queryset_from_cache(self):
...@@ -200,7 +203,7 @@ class LDAPUserListApi(generics.ListAPIView): ...@@ -200,7 +203,7 @@ class LDAPUserListApi(generics.ListAPIView):
class LDAPUserImportAPI(APIView): class LDAPUserImportAPI(APIView):
permission_classes = (IsOrgAdmin,) permission_classes = (IsSuperUser,)
def get_ldap_users(self): def get_ldap_users(self):
username_list = self.request.data.get('username_list', []) username_list = self.request.data.get('username_list', [])
...@@ -229,6 +232,7 @@ class LDAPUserImportAPI(APIView): ...@@ -229,6 +232,7 @@ class LDAPUserImportAPI(APIView):
class LDAPCacheRefreshAPI(generics.RetrieveAPIView): class LDAPCacheRefreshAPI(generics.RetrieveAPIView):
permission_classes = (IsSuperUser,)
def retrieve(self, request, *args, **kwargs): def retrieve(self, request, *args, **kwargs):
try: try:
...@@ -318,3 +322,19 @@ class CommandStorageDeleteAPI(APIView): ...@@ -318,3 +322,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
...@@ -29,3 +29,6 @@ class LDAPUserSerializer(serializers.Serializer): ...@@ -29,3 +29,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)
...@@ -16,4 +16,5 @@ urlpatterns = [ ...@@ -16,4 +16,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