mirror of https://github.com/jumpserver/jumpserver
[Bugfix] 修改users模块一些bug
parent
e1163895e2
commit
a308000d2e
|
@ -1,5 +1,4 @@
|
||||||
# ~*~ coding: utf-8 ~*~
|
# ~*~ coding: utf-8 ~*~
|
||||||
|
|
||||||
# Copyright (C) 2014-2017 Beijing DuiZhan Technology Co.,Ltd. All Rights Reserved.
|
# Copyright (C) 2014-2017 Beijing DuiZhan Technology Co.,Ltd. All Rights Reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the GNU General Public License v2.0 (the "License");
|
# Licensed under the GNU General Public License v2.0 (the "License");
|
||||||
|
@ -22,7 +21,7 @@ from django.shortcuts import get_object_or_404
|
||||||
|
|
||||||
from common.mixins import IDInFilterMixin
|
from common.mixins import IDInFilterMixin
|
||||||
from common.utils import get_object_or_none
|
from common.utils import get_object_or_none
|
||||||
from .hands import IsSuperUser, IsAppUser, IsValidUser, IsSuperUserOrAppUser, \
|
from .hands import IsSuperUser, IsValidUser, IsSuperUserOrAppUser, \
|
||||||
get_user_granted_assets, push_users
|
get_user_granted_assets, push_users
|
||||||
from .models import AssetGroup, Asset, Cluster, SystemUser, AdminUser
|
from .models import AssetGroup, Asset, Cluster, SystemUser, AdminUser
|
||||||
from . import serializers
|
from . import serializers
|
||||||
|
@ -58,63 +57,80 @@ class AssetViewSet(IDInFilterMixin, BulkModelViewSet):
|
||||||
|
|
||||||
|
|
||||||
class AssetGroupViewSet(IDInFilterMixin, BulkModelViewSet):
|
class AssetGroupViewSet(IDInFilterMixin, BulkModelViewSet):
|
||||||
"""Asset group api set, for add,delete,update,list,retrieve resource"""
|
"""
|
||||||
|
Asset group api set, for add,delete,update,list,retrieve resource
|
||||||
|
"""
|
||||||
queryset = AssetGroup.objects.all()
|
queryset = AssetGroup.objects.all()
|
||||||
serializer_class = serializers.AssetGroupSerializer
|
serializer_class = serializers.AssetGroupSerializer
|
||||||
permission_classes = (IsSuperUser,)
|
permission_classes = (IsSuperUser,)
|
||||||
|
|
||||||
|
|
||||||
class AssetUpdateGroupApi(generics.RetrieveUpdateAPIView):
|
class AssetUpdateGroupApi(generics.RetrieveUpdateAPIView):
|
||||||
"""Asset update it's group api"""
|
"""
|
||||||
|
Asset update it's group api
|
||||||
|
"""
|
||||||
queryset = Asset.objects.all()
|
queryset = Asset.objects.all()
|
||||||
serializer_class = serializers.AssetUpdateGroupSerializer
|
serializer_class = serializers.AssetUpdateGroupSerializer
|
||||||
permission_classes = (IsSuperUser,)
|
permission_classes = (IsSuperUser,)
|
||||||
|
|
||||||
|
|
||||||
class AssetGroupUpdateApi(generics.RetrieveUpdateAPIView):
|
class AssetGroupUpdateApi(generics.RetrieveUpdateAPIView):
|
||||||
"""Asset group, update it's asset member"""
|
"""
|
||||||
|
Asset group, update it's asset member
|
||||||
|
"""
|
||||||
queryset = AssetGroup.objects.all()
|
queryset = AssetGroup.objects.all()
|
||||||
serializer_class = serializers.AssetGroupUpdateSerializer
|
serializer_class = serializers.AssetGroupUpdateSerializer
|
||||||
permission_classes = (IsSuperUser,)
|
permission_classes = (IsSuperUser,)
|
||||||
|
|
||||||
|
|
||||||
class AssetGroupUpdateSystemUserApi(generics.RetrieveUpdateAPIView):
|
class AssetGroupUpdateSystemUserApi(generics.RetrieveUpdateAPIView):
|
||||||
"""Asset group push system user"""
|
"""
|
||||||
|
Asset group push system user
|
||||||
|
"""
|
||||||
queryset = AssetGroup.objects.all()
|
queryset = AssetGroup.objects.all()
|
||||||
serializer_class = serializers.AssetGroupUpdateSystemUserSerializer
|
serializer_class = serializers.AssetGroupUpdateSystemUserSerializer
|
||||||
permission_classes = (IsSuperUser,)
|
permission_classes = (IsSuperUser,)
|
||||||
|
|
||||||
|
|
||||||
class ClusterUpdateAssetsApi(generics.RetrieveUpdateAPIView):
|
class ClusterUpdateAssetsApi(generics.RetrieveUpdateAPIView):
|
||||||
"""Cluster update asset member"""
|
"""
|
||||||
|
Cluster update asset member
|
||||||
|
"""
|
||||||
queryset = Cluster.objects.all()
|
queryset = Cluster.objects.all()
|
||||||
serializer_class = serializers.ClusterUpdateAssetsSerializer
|
serializer_class = serializers.ClusterUpdateAssetsSerializer
|
||||||
permission_classes = (IsSuperUser,)
|
permission_classes = (IsSuperUser,)
|
||||||
|
|
||||||
|
|
||||||
class ClusterViewSet(IDInFilterMixin, BulkModelViewSet):
|
class ClusterViewSet(IDInFilterMixin, BulkModelViewSet):
|
||||||
"""Cluster api set, for add,delete,update,list,retrieve resource"""
|
"""
|
||||||
|
Cluster api set, for add,delete,update,list,retrieve resource
|
||||||
|
"""
|
||||||
queryset = Cluster.objects.all()
|
queryset = Cluster.objects.all()
|
||||||
serializer_class = serializers.ClusterSerializer
|
serializer_class = serializers.ClusterSerializer
|
||||||
permission_classes = (IsSuperUser,)
|
permission_classes = (IsSuperUser,)
|
||||||
|
|
||||||
|
|
||||||
class AdminUserViewSet(IDInFilterMixin, BulkModelViewSet):
|
class AdminUserViewSet(IDInFilterMixin, BulkModelViewSet):
|
||||||
"""Admin user api set, for add,delete,update,list,retrieve resource"""
|
"""
|
||||||
|
Admin user api set, for add,delete,update,list,retrieve resource
|
||||||
|
"""
|
||||||
queryset = AdminUser.objects.all()
|
queryset = AdminUser.objects.all()
|
||||||
serializer_class = serializers.AdminUserSerializer
|
serializer_class = serializers.AdminUserSerializer
|
||||||
permission_classes = (IsSuperUser,)
|
permission_classes = (IsSuperUser,)
|
||||||
|
|
||||||
|
|
||||||
class SystemUserViewSet(IDInFilterMixin, BulkModelViewSet):
|
class SystemUserViewSet(IDInFilterMixin, BulkModelViewSet):
|
||||||
"""System user api set, for add,delete,update,list,retrieve resource"""
|
"""
|
||||||
|
System user api set, for add,delete,update,list,retrieve resource
|
||||||
|
"""
|
||||||
queryset = SystemUser.objects.all()
|
queryset = SystemUser.objects.all()
|
||||||
serializer_class = serializers.SystemUserSerializer
|
serializer_class = serializers.SystemUserSerializer
|
||||||
permission_classes = (IsSuperUserOrAppUser,)
|
permission_classes = (IsSuperUserOrAppUser,)
|
||||||
|
|
||||||
|
|
||||||
class SystemUserUpdateApi(generics.RetrieveUpdateAPIView):
|
class SystemUserUpdateApi(generics.RetrieveUpdateAPIView):
|
||||||
"""Asset update it's system user
|
"""
|
||||||
|
Asset update it's system user
|
||||||
|
|
||||||
when update then push system user to asset.
|
when update then push system user to asset.
|
||||||
"""
|
"""
|
||||||
|
@ -134,28 +150,36 @@ class SystemUserUpdateApi(generics.RetrieveUpdateAPIView):
|
||||||
|
|
||||||
|
|
||||||
class SystemUserUpdateAssetsApi(generics.RetrieveUpdateAPIView):
|
class SystemUserUpdateAssetsApi(generics.RetrieveUpdateAPIView):
|
||||||
"""System user update it's assets"""
|
"""
|
||||||
|
System user update it's assets
|
||||||
|
"""
|
||||||
queryset = SystemUser.objects.all()
|
queryset = SystemUser.objects.all()
|
||||||
serializer_class = serializers.SystemUserUpdateAssetsSerializer
|
serializer_class = serializers.SystemUserUpdateAssetsSerializer
|
||||||
permission_classes = (IsSuperUser,)
|
permission_classes = (IsSuperUser,)
|
||||||
|
|
||||||
|
|
||||||
class SystemUserUpdateAssetGroupApi(generics.RetrieveUpdateAPIView):
|
class SystemUserUpdateAssetGroupApi(generics.RetrieveUpdateAPIView):
|
||||||
"""System user update asset group"""
|
"""
|
||||||
|
System user update asset group
|
||||||
|
"""
|
||||||
queryset = SystemUser.objects.all()
|
queryset = SystemUser.objects.all()
|
||||||
serializer_class = serializers.SystemUserUpdateAssetGroupSerializer
|
serializer_class = serializers.SystemUserUpdateAssetGroupSerializer
|
||||||
permission_classes = (IsSuperUser,)
|
permission_classes = (IsSuperUser,)
|
||||||
|
|
||||||
|
|
||||||
class AssetListUpdateApi(IDInFilterMixin, ListBulkCreateUpdateDestroyAPIView):
|
class AssetListUpdateApi(IDInFilterMixin, ListBulkCreateUpdateDestroyAPIView):
|
||||||
"""Asset bulk update api"""
|
"""
|
||||||
|
Asset bulk update api
|
||||||
|
"""
|
||||||
queryset = Asset.objects.all()
|
queryset = Asset.objects.all()
|
||||||
serializer_class = serializers.AssetSerializer
|
serializer_class = serializers.AssetSerializer
|
||||||
permission_classes = (IsSuperUser,)
|
permission_classes = (IsSuperUser,)
|
||||||
|
|
||||||
|
|
||||||
class SystemUserAuthInfoApi(generics.RetrieveAPIView):
|
class SystemUserAuthInfoApi(generics.RetrieveAPIView):
|
||||||
"""Get system user auth info"""
|
"""
|
||||||
|
Get system user auth info
|
||||||
|
"""
|
||||||
queryset = SystemUser.objects.all()
|
queryset = SystemUser.objects.all()
|
||||||
permission_classes = (IsSuperUserOrAppUser,)
|
permission_classes = (IsSuperUserOrAppUser,)
|
||||||
|
|
||||||
|
@ -172,7 +196,9 @@ class SystemUserAuthInfoApi(generics.RetrieveAPIView):
|
||||||
|
|
||||||
|
|
||||||
class AssetRefreshHardwareView(generics.RetrieveAPIView):
|
class AssetRefreshHardwareView(generics.RetrieveAPIView):
|
||||||
"""Refresh asset hardware info"""
|
"""
|
||||||
|
Refresh asset hardware info
|
||||||
|
"""
|
||||||
queryset = Asset.objects.all()
|
queryset = Asset.objects.all()
|
||||||
serializer_class = serializers.AssetSerializer
|
serializer_class = serializers.AssetSerializer
|
||||||
permission_classes = (IsSuperUser,)
|
permission_classes = (IsSuperUser,)
|
||||||
|
@ -181,7 +207,6 @@ class AssetRefreshHardwareView(generics.RetrieveAPIView):
|
||||||
asset_id = kwargs.get('pk')
|
asset_id = kwargs.get('pk')
|
||||||
asset = get_object_or_404(Asset, pk=asset_id)
|
asset = get_object_or_404(Asset, pk=asset_id)
|
||||||
summary = update_assets_hardware_info([asset])
|
summary = update_assets_hardware_info([asset])
|
||||||
print(summary)
|
|
||||||
if summary.get('dark'):
|
if summary.get('dark'):
|
||||||
return Response(summary['dark'].values(), status=501)
|
return Response(summary['dark'].values(), status=501)
|
||||||
else:
|
else:
|
||||||
|
@ -189,7 +214,9 @@ class AssetRefreshHardwareView(generics.RetrieveAPIView):
|
||||||
|
|
||||||
|
|
||||||
class AssetAdminUserTestView(AssetRefreshHardwareView):
|
class AssetAdminUserTestView(AssetRefreshHardwareView):
|
||||||
"""Test asset admin user connectivity"""
|
"""
|
||||||
|
Test asset admin user connectivity
|
||||||
|
"""
|
||||||
queryset = Asset.objects.all()
|
queryset = Asset.objects.all()
|
||||||
permission_classes = (IsSuperUser,)
|
permission_classes = (IsSuperUser,)
|
||||||
|
|
||||||
|
@ -204,7 +231,9 @@ class AssetAdminUserTestView(AssetRefreshHardwareView):
|
||||||
|
|
||||||
|
|
||||||
class AssetGroupPushSystemUserView(generics.UpdateAPIView):
|
class AssetGroupPushSystemUserView(generics.UpdateAPIView):
|
||||||
"""Asset group push system user api"""
|
"""
|
||||||
|
Asset group push system user api
|
||||||
|
"""
|
||||||
queryset = AssetGroup.objects.all()
|
queryset = AssetGroup.objects.all()
|
||||||
permission_classes = (IsSuperUser,)
|
permission_classes = (IsSuperUser,)
|
||||||
serializer_class = serializers.AssetSerializer
|
serializer_class = serializers.AssetSerializer
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from rest_framework import viewsets, serializers, generics
|
from rest_framework import serializers
|
||||||
from rest_framework_bulk.serializers import BulkListSerializer
|
from rest_framework_bulk.serializers import BulkListSerializer
|
||||||
|
|
||||||
from common.mixins import BulkSerializerMixin
|
from common.mixins import BulkSerializerMixin
|
||||||
|
@ -9,6 +9,9 @@ from .const import ADMIN_USER_CONN_CACHE_KEY, SYSTEM_USER_CONN_CACHE_KEY
|
||||||
|
|
||||||
|
|
||||||
class AssetGroupSerializer(BulkSerializerMixin, serializers.ModelSerializer):
|
class AssetGroupSerializer(BulkSerializerMixin, serializers.ModelSerializer):
|
||||||
|
"""
|
||||||
|
资产组序列化数据模型
|
||||||
|
"""
|
||||||
assets_amount = serializers.SerializerMethodField()
|
assets_amount = serializers.SerializerMethodField()
|
||||||
assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all())
|
assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all())
|
||||||
|
|
||||||
|
@ -23,6 +26,9 @@ class AssetGroupSerializer(BulkSerializerMixin, serializers.ModelSerializer):
|
||||||
|
|
||||||
|
|
||||||
class AssetUpdateGroupSerializer(serializers.ModelSerializer):
|
class AssetUpdateGroupSerializer(serializers.ModelSerializer):
|
||||||
|
"""
|
||||||
|
资产更新自己所在资产组的请求数据结构定义
|
||||||
|
"""
|
||||||
groups = serializers.PrimaryKeyRelatedField(many=True, queryset=AssetGroup.objects.all())
|
groups = serializers.PrimaryKeyRelatedField(many=True, queryset=AssetGroup.objects.all())
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -31,6 +37,9 @@ class AssetUpdateGroupSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
|
|
||||||
class AssetUpdateSystemUserSerializer(serializers.ModelSerializer):
|
class AssetUpdateSystemUserSerializer(serializers.ModelSerializer):
|
||||||
|
"""
|
||||||
|
资产更新其系统用户请求的数据结构定义
|
||||||
|
"""
|
||||||
system_users = serializers.PrimaryKeyRelatedField(many=True, queryset=SystemUser.objects.all())
|
system_users = serializers.PrimaryKeyRelatedField(many=True, queryset=SystemUser.objects.all())
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -39,7 +48,9 @@ class AssetUpdateSystemUserSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
|
|
||||||
class AssetGroupUpdateSerializer(serializers.ModelSerializer):
|
class AssetGroupUpdateSerializer(serializers.ModelSerializer):
|
||||||
"""update the asset group, and add or delete the asset to the group"""
|
"""
|
||||||
|
资产组更新需要的数据结构
|
||||||
|
"""
|
||||||
assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all())
|
assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all())
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -48,6 +59,9 @@ class AssetGroupUpdateSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
|
|
||||||
class AssetGroupUpdateSystemUserSerializer(serializers.ModelSerializer):
|
class AssetGroupUpdateSystemUserSerializer(serializers.ModelSerializer):
|
||||||
|
"""
|
||||||
|
资产组更新系统用户定义的数据结构
|
||||||
|
"""
|
||||||
system_users = serializers.PrimaryKeyRelatedField(many=True, queryset=SystemUser.objects.all())
|
system_users = serializers.PrimaryKeyRelatedField(many=True, queryset=SystemUser.objects.all())
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -56,6 +70,9 @@ class AssetGroupUpdateSystemUserSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
|
|
||||||
class ClusterUpdateAssetsSerializer(serializers.ModelSerializer):
|
class ClusterUpdateAssetsSerializer(serializers.ModelSerializer):
|
||||||
|
"""
|
||||||
|
集群更新资产数据结构
|
||||||
|
"""
|
||||||
assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all())
|
assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all())
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -64,6 +81,9 @@ class ClusterUpdateAssetsSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
|
|
||||||
class AdminUserSerializer(serializers.ModelSerializer):
|
class AdminUserSerializer(serializers.ModelSerializer):
|
||||||
|
"""
|
||||||
|
管理用户
|
||||||
|
"""
|
||||||
assets_amount = serializers.SerializerMethodField()
|
assets_amount = serializers.SerializerMethodField()
|
||||||
unreachable_amount = serializers.SerializerMethodField()
|
unreachable_amount = serializers.SerializerMethodField()
|
||||||
|
|
||||||
|
@ -89,6 +109,9 @@ class AdminUserSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
|
|
||||||
class SystemUserSerializer(serializers.ModelSerializer):
|
class SystemUserSerializer(serializers.ModelSerializer):
|
||||||
|
"""
|
||||||
|
系统用户
|
||||||
|
"""
|
||||||
unreachable_amount = serializers.SerializerMethodField()
|
unreachable_amount = serializers.SerializerMethodField()
|
||||||
assets_amount = serializers.SerializerMethodField()
|
assets_amount = serializers.SerializerMethodField()
|
||||||
|
|
||||||
|
@ -113,12 +136,18 @@ class SystemUserSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
|
|
||||||
class AssetSystemUserSerializer(serializers.ModelSerializer):
|
class AssetSystemUserSerializer(serializers.ModelSerializer):
|
||||||
|
"""
|
||||||
|
查看授权的资产系统用户的数据结构,这个和AssetSerializer不同,字段少
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = SystemUser
|
model = SystemUser
|
||||||
fields = ('id', 'name', 'username', 'priority', 'protocol', 'comment',)
|
fields = ('id', 'name', 'username', 'priority', 'protocol', 'comment',)
|
||||||
|
|
||||||
|
|
||||||
class SystemUserUpdateAssetsSerializer(serializers.ModelSerializer):
|
class SystemUserUpdateAssetsSerializer(serializers.ModelSerializer):
|
||||||
|
"""
|
||||||
|
系统用户更新关联资产的数据结构
|
||||||
|
"""
|
||||||
assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all())
|
assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all())
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -127,6 +156,9 @@ class SystemUserUpdateAssetsSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
|
|
||||||
class SystemUserUpdateAssetGroupSerializer(serializers.ModelSerializer):
|
class SystemUserUpdateAssetGroupSerializer(serializers.ModelSerializer):
|
||||||
|
"""
|
||||||
|
系统用户更新资产组的api
|
||||||
|
"""
|
||||||
asset_groups = serializers.PrimaryKeyRelatedField(many=True, queryset=AssetGroup.objects.all())
|
asset_groups = serializers.PrimaryKeyRelatedField(many=True, queryset=AssetGroup.objects.all())
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -135,12 +167,18 @@ class SystemUserUpdateAssetGroupSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
|
|
||||||
class SystemUserSimpleSerializer(serializers.ModelSerializer):
|
class SystemUserSimpleSerializer(serializers.ModelSerializer):
|
||||||
|
"""
|
||||||
|
系统用户最基本信息的数据结构
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = SystemUser
|
model = SystemUser
|
||||||
fields = ('id', 'name', 'username')
|
fields = ('id', 'name', 'username')
|
||||||
|
|
||||||
|
|
||||||
class AssetSerializer(BulkSerializerMixin, serializers.ModelSerializer):
|
class AssetSerializer(BulkSerializerMixin, serializers.ModelSerializer):
|
||||||
|
"""
|
||||||
|
资产的数据结构
|
||||||
|
"""
|
||||||
class Meta(object):
|
class Meta(object):
|
||||||
model = Asset
|
model = Asset
|
||||||
list_serializer_class = BulkListSerializer
|
list_serializer_class = BulkListSerializer
|
||||||
|
@ -157,6 +195,9 @@ class AssetSerializer(BulkSerializerMixin, serializers.ModelSerializer):
|
||||||
|
|
||||||
|
|
||||||
class AssetGrantedSerializer(serializers.ModelSerializer):
|
class AssetGrantedSerializer(serializers.ModelSerializer):
|
||||||
|
"""
|
||||||
|
被授权资产的数据结构
|
||||||
|
"""
|
||||||
system_users_granted = AssetSystemUserSerializer(many=True, read_only=True)
|
system_users_granted = AssetSystemUserSerializer(many=True, read_only=True)
|
||||||
is_inherited = serializers.SerializerMethodField()
|
is_inherited = serializers.SerializerMethodField()
|
||||||
system_users_join = serializers.SerializerMethodField()
|
system_users_join = serializers.SerializerMethodField()
|
||||||
|
@ -180,7 +221,9 @@ class AssetGrantedSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
|
|
||||||
class MyAssetGrantedSerializer(AssetGrantedSerializer):
|
class MyAssetGrantedSerializer(AssetGrantedSerializer):
|
||||||
"""Remove ip and port from asset for security"""
|
"""
|
||||||
|
普通用户获取授权的资产定义的数据结构
|
||||||
|
"""
|
||||||
|
|
||||||
class Meta(object):
|
class Meta(object):
|
||||||
model = Asset
|
model = Asset
|
||||||
|
@ -189,6 +232,9 @@ class MyAssetGrantedSerializer(AssetGrantedSerializer):
|
||||||
|
|
||||||
|
|
||||||
class ClusterSerializer(BulkSerializerMixin, serializers.ModelSerializer):
|
class ClusterSerializer(BulkSerializerMixin, serializers.ModelSerializer):
|
||||||
|
"""
|
||||||
|
cluster
|
||||||
|
"""
|
||||||
assets_amount = serializers.SerializerMethodField()
|
assets_amount = serializers.SerializerMethodField()
|
||||||
admin_user_name = serializers.SerializerMethodField()
|
admin_user_name = serializers.SerializerMethodField()
|
||||||
assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all())
|
assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all())
|
||||||
|
@ -210,6 +256,9 @@ class ClusterSerializer(BulkSerializerMixin, serializers.ModelSerializer):
|
||||||
|
|
||||||
|
|
||||||
class AssetGroupGrantedSerializer(BulkSerializerMixin, serializers.ModelSerializer):
|
class AssetGroupGrantedSerializer(BulkSerializerMixin, serializers.ModelSerializer):
|
||||||
|
"""
|
||||||
|
授权资产组
|
||||||
|
"""
|
||||||
assets_granted = AssetGrantedSerializer(many=True, read_only=True)
|
assets_granted = AssetGrantedSerializer(many=True, read_only=True)
|
||||||
assets_amount = serializers.SerializerMethodField()
|
assets_amount = serializers.SerializerMethodField()
|
||||||
|
|
||||||
|
@ -224,6 +273,9 @@ class AssetGroupGrantedSerializer(BulkSerializerMixin, serializers.ModelSerializ
|
||||||
|
|
||||||
|
|
||||||
class MyAssetGroupGrantedSerializer(serializers.ModelSerializer):
|
class MyAssetGroupGrantedSerializer(serializers.ModelSerializer):
|
||||||
|
"""
|
||||||
|
普通用户授权资产组结构
|
||||||
|
"""
|
||||||
assets_granted = MyAssetGrantedSerializer(many=True, read_only=True)
|
assets_granted = MyAssetGrantedSerializer(many=True, read_only=True)
|
||||||
assets_amount = serializers.SerializerMethodField()
|
assets_amount = serializers.SerializerMethodField()
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,6 @@ urlpatterns = [
|
||||||
url(r'^users/', include('users.urls.views_urls', namespace='users')),
|
url(r'^users/', include('users.urls.views_urls', namespace='users')),
|
||||||
url(r'^assets/', include('assets.urls.views_urls', namespace='assets')),
|
url(r'^assets/', include('assets.urls.views_urls', namespace='assets')),
|
||||||
url(r'^perms/', include('perms.urls.views_urls', namespace='perms')),
|
url(r'^perms/', include('perms.urls.views_urls', namespace='perms')),
|
||||||
# url(r'^audits/', include('audits.urls.views_urls', namespace='audits')),
|
|
||||||
url(r'^terminal/', include('terminal.urls.views_urls', namespace='terminal')),
|
url(r'^terminal/', include('terminal.urls.views_urls', namespace='terminal')),
|
||||||
url(r'^ops/', include('ops.urls.view_urls', namespace='ops')),
|
url(r'^ops/', include('ops.urls.view_urls', namespace='ops')),
|
||||||
|
|
||||||
|
@ -24,9 +23,10 @@ urlpatterns = [
|
||||||
url(r'^api/users/', include('users.urls.api_urls', namespace='api-users')),
|
url(r'^api/users/', include('users.urls.api_urls', namespace='api-users')),
|
||||||
url(r'^api/assets/', include('assets.urls.api_urls', namespace='api-assets')),
|
url(r'^api/assets/', include('assets.urls.api_urls', namespace='api-assets')),
|
||||||
url(r'^api/perms/', include('perms.urls.api_urls', namespace='api-perms')),
|
url(r'^api/perms/', include('perms.urls.api_urls', namespace='api-perms')),
|
||||||
# url(r'^api/audits/', include('audits.urls.api_urls', namespace='api-audits')),
|
|
||||||
url(r'^api/terminal/', include('terminal.urls.api_urls', namespace='api-terminal')),
|
url(r'^api/terminal/', include('terminal.urls.api_urls', namespace='api-terminal')),
|
||||||
url(r'^api/ops/', include('ops.urls.api_urls', namespace='api-ops')),
|
url(r'^api/ops/', include('ops.urls.api_urls', namespace='api-ops')),
|
||||||
|
|
||||||
|
# External apps url
|
||||||
url(r'^captcha/', include('captcha.urls')),
|
url(r'^captcha/', include('captcha.urls')),
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -4,17 +4,12 @@ from django.db import models
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
from common.utils import date_expired_default, combine_seq
|
from common.utils import date_expired_default
|
||||||
|
|
||||||
|
|
||||||
class AssetPermission(models.Model):
|
class AssetPermission(models.Model):
|
||||||
from users.models import User, UserGroup
|
from users.models import User, UserGroup
|
||||||
from assets.models import Asset, AssetGroup, SystemUser
|
from assets.models import Asset, AssetGroup, SystemUser
|
||||||
# PRIVATE_FOR_CHOICE = (
|
|
||||||
# ('N', 'None'),
|
|
||||||
# ('U', 'user'),
|
|
||||||
# ('G', 'user group'),
|
|
||||||
# )
|
|
||||||
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
|
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
|
||||||
name = models.CharField(
|
name = models.CharField(
|
||||||
max_length=128, unique=True, verbose_name=_('Name'))
|
max_length=128, unique=True, verbose_name=_('Name'))
|
||||||
|
@ -38,14 +33,14 @@ class AssetPermission(models.Model):
|
||||||
auto_now_add=True, verbose_name=_('Date created'))
|
auto_now_add=True, verbose_name=_('Date created'))
|
||||||
comment = models.TextField(verbose_name=_('Comment'), blank=True)
|
comment = models.TextField(verbose_name=_('Comment'), blank=True)
|
||||||
|
|
||||||
def __unicode__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_valid(self):
|
def is_valid(self):
|
||||||
if self.date_expired < timezone.now() and self.is_active:
|
if self.date_expired < timezone.now() and self.is_active:
|
||||||
return True
|
return True
|
||||||
return True
|
return False
|
||||||
|
|
||||||
def get_granted_users(self):
|
def get_granted_users(self):
|
||||||
return list(set(self.users.all()) | self.get_granted_user_groups_member())
|
return list(set(self.users.all()) | self.get_granted_user_groups_member())
|
||||||
|
@ -73,8 +68,8 @@ class AssetPermission(models.Model):
|
||||||
assets.add(asset)
|
assets.add(asset)
|
||||||
return assets
|
return assets
|
||||||
|
|
||||||
class Meta:
|
# class Meta:
|
||||||
db_table = 'asset_permission'
|
# db_table = 'asset_permission'
|
||||||
|
|
||||||
|
|
||||||
# def change_permission(sender, **kwargs):
|
# def change_permission(sender, **kwargs):
|
||||||
|
|
|
@ -168,22 +168,6 @@ def get_user_granted_system_users(user):
|
||||||
return system_users_dict
|
return system_users_dict
|
||||||
|
|
||||||
|
|
||||||
def get_user_groups_granted_in_asset(asset):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def get_users_granted_in_asset(asset):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def get_user_groups_granted_in_asset_group(asset):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def get_users_granted_in_asset_group(asset):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def push_system_user(assets, system_user):
|
def push_system_user(assets, system_user):
|
||||||
logger.info('Push system user %s' % system_user.name)
|
logger.info('Push system user %s' % system_user.name)
|
||||||
for asset in assets:
|
for asset in assets:
|
||||||
|
|
|
@ -245,7 +245,8 @@ jumpserver.initDataTable = function (options) {
|
||||||
// buttons: ['excel', 'pdf', 'print'],
|
// buttons: ['excel', 'pdf', 'print'],
|
||||||
// columnDefs: [{target: 0, createdCell: ()=>{}}, ...],
|
// columnDefs: [{target: 0, createdCell: ()=>{}}, ...],
|
||||||
// uc_html: '<a>header button</a>',
|
// uc_html: '<a>header button</a>',
|
||||||
// op_html: 'div.btn-group?'
|
// op_html: 'div.btn-group?',
|
||||||
|
// paging: true
|
||||||
// }
|
// }
|
||||||
var ele = options.ele || $('.dataTable');
|
var ele = options.ele || $('.dataTable');
|
||||||
var columnDefs = [
|
var columnDefs = [
|
||||||
|
|
|
@ -8,17 +8,18 @@ import os
|
||||||
from rest_framework import viewsets, serializers
|
from rest_framework import viewsets, serializers
|
||||||
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 django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404, redirect
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.conf import settings
|
from django.core.files.storage import default_storage
|
||||||
|
from django.http import HttpResponseNotFound
|
||||||
|
|
||||||
from common.utils import get_object_or_none
|
from common.utils import get_object_or_none
|
||||||
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
|
SessionSerializer, TaskSerializer, ReplaySerializer
|
||||||
from .hands import IsSuperUserOrAppUser, IsAppUser, \
|
from .hands import IsSuperUserOrAppUser, IsAppUser, \
|
||||||
IsSuperUserOrAppUserOrUserReadonly
|
IsSuperUserOrAppUserOrUserReadonly
|
||||||
from .backends import get_command_store, get_replay_store, SessionCommandSerializer
|
from .backends import get_command_store, SessionCommandSerializer
|
||||||
|
|
||||||
logger = logging.getLogger(__file__)
|
logger = logging.getLogger(__file__)
|
||||||
|
|
||||||
|
@ -149,46 +150,6 @@ class TaskViewSet(viewsets.ModelViewSet):
|
||||||
serializer_class = TaskSerializer
|
serializer_class = TaskSerializer
|
||||||
permission_classes = (IsSuperUserOrAppUser,)
|
permission_classes = (IsSuperUserOrAppUser,)
|
||||||
|
|
||||||
# def get_queryset(self):
|
|
||||||
# terminal_id = self.kwargs.get("terminal", None)
|
|
||||||
# if terminal_id:
|
|
||||||
# terminal = get_object_or_404(Terminal, id=terminal_id)
|
|
||||||
# self.queryset = terminal.status_set.all()
|
|
||||||
#
|
|
||||||
# if hasattr(self.request.user, "terminal"):
|
|
||||||
# terminal = self.request.user.terminal
|
|
||||||
# self.queryset = terminal.status_set.all()
|
|
||||||
# return self.queryset
|
|
||||||
|
|
||||||
|
|
||||||
class SessionReplayAPI(APIView):
|
|
||||||
permission_classes = (IsSuperUserOrAppUser,)
|
|
||||||
|
|
||||||
def post(self, request, **kwargs):
|
|
||||||
session_id = kwargs.get("pk", None)
|
|
||||||
session = get_object_or_404(Session, id=session_id)
|
|
||||||
record_dir = settings.CONFIG.SESSION_RECORDE_DIR
|
|
||||||
date = session.date_start.strftime("%Y-%m-%d")
|
|
||||||
record_dir = os.path.join(record_dir, date, str(session.id))
|
|
||||||
record_filename = os.path.join(record_dir, "replay.tar.gz2")
|
|
||||||
|
|
||||||
if not os.path.isdir(record_dir):
|
|
||||||
try:
|
|
||||||
os.makedirs(record_dir)
|
|
||||||
except FileExistsError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
archive_stream = request.data.get("archive")
|
|
||||||
if not archive_stream:
|
|
||||||
return Response("None file upload", status=400)
|
|
||||||
|
|
||||||
with open(record_filename, 'wb') as f:
|
|
||||||
for chunk in archive_stream.chunks():
|
|
||||||
f.write(chunk)
|
|
||||||
session.has_replay = True
|
|
||||||
session.save()
|
|
||||||
return Response({"session_id": session.id}, status=201)
|
|
||||||
|
|
||||||
|
|
||||||
class CommandViewSet(viewsets.ViewSet):
|
class CommandViewSet(viewsets.ViewSet):
|
||||||
"""接受app发送来的command log, 格式如下
|
"""接受app发送来的command log, 格式如下
|
||||||
|
@ -208,7 +169,7 @@ class CommandViewSet(viewsets.ViewSet):
|
||||||
permission_classes = (IsSuperUserOrAppUser,)
|
permission_classes = (IsSuperUserOrAppUser,)
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
self.command_store.filter(**dict(self.request.data))
|
self.command_store.filter(**dict(self.request.query_params))
|
||||||
|
|
||||||
def create(self, request, *args, **kwargs):
|
def create(self, request, *args, **kwargs):
|
||||||
serializer = self.serializer_class(data=request.data, many=True)
|
serializer = self.serializer_class(data=request.data, many=True)
|
||||||
|
@ -227,3 +188,43 @@ class CommandViewSet(viewsets.ViewSet):
|
||||||
queryset = list(self.command_store.all())
|
queryset = list(self.command_store.all())
|
||||||
serializer = self.serializer_class(queryset, many=True)
|
serializer = self.serializer_class(queryset, many=True)
|
||||||
return Response(serializer.data)
|
return Response(serializer.data)
|
||||||
|
|
||||||
|
|
||||||
|
class SessionReplayViewSet(viewsets.ViewSet):
|
||||||
|
serializer_class = ReplaySerializer
|
||||||
|
permission_classes = ()
|
||||||
|
session = None
|
||||||
|
|
||||||
|
def gen_session_path(self):
|
||||||
|
date = self.session.date_start.strftime('%Y-%m-%d')
|
||||||
|
return os.path.join(date, str(self.session.id)+'.gz')
|
||||||
|
|
||||||
|
def create(self, request, *args, **kwargs):
|
||||||
|
session_id = kwargs.get('pk')
|
||||||
|
self.session = get_object_or_404(Session, id=session_id)
|
||||||
|
serializer = self.serializer_class(data=request.data)
|
||||||
|
|
||||||
|
if serializer.is_valid():
|
||||||
|
file = serializer.validated_data['file']
|
||||||
|
file_path = self.gen_session_path()
|
||||||
|
try:
|
||||||
|
default_storage.save(file_path, file)
|
||||||
|
return Response({'url': default_storage.url(file_path)},
|
||||||
|
status=201)
|
||||||
|
except IOError:
|
||||||
|
return Response("Save error", status=500)
|
||||||
|
else:
|
||||||
|
logger.error(
|
||||||
|
'Update load data invalid: {}'.format(serializer.errors))
|
||||||
|
return Response({'msg': serializer.errors}, status=401)
|
||||||
|
|
||||||
|
def retrieve(self, request, *args, **kwargs):
|
||||||
|
session_id = kwargs.get('pk')
|
||||||
|
self.session = get_object_or_404(Session, id=session_id)
|
||||||
|
path = self.gen_session_path()
|
||||||
|
|
||||||
|
if default_storage.exists(path):
|
||||||
|
url = default_storage.url(path)
|
||||||
|
return redirect(url)
|
||||||
|
else:
|
||||||
|
return HttpResponseNotFound()
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
from importlib import import_module
|
from importlib import import_module
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
from .command.serializers import SessionCommandSerializer
|
from .command.serializers import SessionCommandSerializer
|
||||||
|
|
||||||
|
|
||||||
|
@ -10,8 +8,3 @@ def get_command_store():
|
||||||
command_store = command_engine.CommandStore()
|
command_store = command_engine.CommandStore()
|
||||||
return command_store
|
return command_store
|
||||||
|
|
||||||
|
|
||||||
def get_replay_store():
|
|
||||||
replay_engine = import_module(settings.REPLAY_STORE_BACKEND)
|
|
||||||
replay_store = replay_engine.ReplayStore()
|
|
||||||
return replay_store
|
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
# ~*~ coding: utf-8 ~*~
|
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
# coding: utf-8
|
|
||||||
import abc
|
|
||||||
|
|
||||||
|
|
||||||
class ReplayBase(object):
|
|
||||||
__metaclass__ = abc.ABCMeta
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def save(self, proxy_log_id, output, timestamp):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def filter(self, date_from_ts=None, proxy_log_id=None):
|
|
||||||
pass
|
|
|
@ -1,8 +0,0 @@
|
||||||
# ~*~ coding: utf-8 ~*~
|
|
||||||
|
|
||||||
from .base import ReplayBase
|
|
||||||
|
|
||||||
|
|
||||||
class ReplayStore(ReplayBase):
|
|
||||||
pass
|
|
||||||
|
|
|
@ -62,3 +62,8 @@ class TaskSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
model = Task
|
model = Task
|
||||||
|
|
||||||
|
|
||||||
|
class ReplaySerializer(serializers.Serializer):
|
||||||
|
file = serializers.FileField()
|
||||||
|
|
||||||
|
|
|
@ -11,13 +11,15 @@ app_name = 'terminal'
|
||||||
|
|
||||||
router = routers.DefaultRouter()
|
router = routers.DefaultRouter()
|
||||||
router.register(r'v1/terminal/(?P<terminal>[a-zA-Z0-9\-]{36})?/?status', api.StatusViewSet, 'terminal-status')
|
router.register(r'v1/terminal/(?P<terminal>[a-zA-Z0-9\-]{36})?/?status', api.StatusViewSet, 'terminal-status')
|
||||||
router.register(r'v1/terminal/(?P<terminal>a-zA-Z0-9\-]{36})?/?sessions', api.SessionViewSet, 'terminal-sessions')
|
router.register(r'v1/terminal/(?P<terminal>[a-zA-Z0-9\-]{36})?/?sessions', api.SessionViewSet, 'terminal-sessions')
|
||||||
router.register(r'v1/tasks', api.TaskViewSet, 'tasks')
|
router.register(r'v1/tasks', api.TaskViewSet, 'tasks')
|
||||||
router.register(r'v1/terminal', api.TerminalViewSet, 'terminal')
|
router.register(r'v1/terminal', api.TerminalViewSet, 'terminal')
|
||||||
router.register(r'v1/command', api.CommandViewSet, 'command')
|
router.register(r'v1/command', api.CommandViewSet, 'command')
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^v1/sessions/(?P<pk>[0-9a-zA-Z\-_]+)/replay/$', api.SessionReplayAPI.as_view(), name='session-replay'),
|
url(r'^v1/sessions/(?P<pk>[0-9a-zA-Z\-]{36})/replay/$',
|
||||||
|
api.SessionReplayViewSet.as_view({'get': 'retrieve', 'post': 'create'}),
|
||||||
|
name='session-replay'),
|
||||||
]
|
]
|
||||||
|
|
||||||
urlpatterns += router.urls
|
urlpatterns += router.urls
|
||||||
|
|
|
@ -21,7 +21,7 @@ logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class UserViewSet(BulkModelViewSet):
|
class UserViewSet(BulkModelViewSet):
|
||||||
queryset = User.objects.all()
|
queryset = User.objects.exclude(role="App")
|
||||||
# queryset = User.objects.all().exclude(role="App").order_by("date_joined")
|
# queryset = User.objects.all().exclude(role="App").order_by("date_joined")
|
||||||
serializer_class = UserSerializer
|
serializer_class = UserSerializer
|
||||||
permission_classes = (IsSuperUser,)
|
permission_classes = (IsSuperUser,)
|
||||||
|
|
|
@ -13,17 +13,23 @@ from .models import User, UserGroup
|
||||||
class UserLoginForm(AuthenticationForm):
|
class UserLoginForm(AuthenticationForm):
|
||||||
username = forms.CharField(label=_('Username'), max_length=100)
|
username = forms.CharField(label=_('Username'), max_length=100)
|
||||||
password = forms.CharField(
|
password = forms.CharField(
|
||||||
label=_('Password'), widget=forms.PasswordInput, max_length=100,
|
label=_('Password'), widget=forms.PasswordInput,
|
||||||
strip=False)
|
max_length=128, strip=False
|
||||||
|
)
|
||||||
captcha = CaptchaField()
|
captcha = CaptchaField()
|
||||||
|
|
||||||
|
|
||||||
class UserCreateUpdateForm(forms.ModelForm):
|
class UserCreateUpdateForm(forms.ModelForm):
|
||||||
|
password = forms.CharField(
|
||||||
|
label=_('Password'), widget=forms.PasswordInput,
|
||||||
|
max_length=128, strip=False, required=False,
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = User
|
model = User
|
||||||
fields = [
|
fields = [
|
||||||
'username', 'name', 'email', 'groups', 'wechat',
|
'username', 'name', 'email', 'groups', 'wechat',
|
||||||
'phone', 'enable_otp', 'role', 'date_expired', 'comment',
|
'phone', 'role', 'date_expired', 'comment', 'password'
|
||||||
]
|
]
|
||||||
help_texts = {
|
help_texts = {
|
||||||
'username': '* required',
|
'username': '* required',
|
||||||
|
@ -36,6 +42,14 @@ class UserCreateUpdateForm(forms.ModelForm):
|
||||||
'data-placeholder': _('Join user groups')}),
|
'data-placeholder': _('Join user groups')}),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def save(self, commit=True):
|
||||||
|
user = super().save(commit=commit)
|
||||||
|
password = self.cleaned_data.get('password')
|
||||||
|
if password:
|
||||||
|
user.set_password(password)
|
||||||
|
user.save()
|
||||||
|
return user
|
||||||
|
|
||||||
|
|
||||||
class UserProfileForm(forms.ModelForm):
|
class UserProfileForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -115,15 +129,11 @@ class UserPublicKeyForm(forms.Form):
|
||||||
|
|
||||||
|
|
||||||
class UserBulkUpdateForm(forms.ModelForm):
|
class UserBulkUpdateForm(forms.ModelForm):
|
||||||
role = forms.ChoiceField(
|
|
||||||
label=_('Role'),
|
|
||||||
choices=[('Admin', 'Administrator'), ('User', 'User')],
|
|
||||||
)
|
|
||||||
users = forms.MultipleChoiceField(
|
users = forms.MultipleChoiceField(
|
||||||
required=True,
|
required=True,
|
||||||
help_text='* required',
|
help_text='* required',
|
||||||
label=_('Select users'),
|
label=_('Select users'),
|
||||||
# choices=[(user.id, user.name) for user in User.objects.all()],
|
choices=[(user.id, user.name) for user in User.objects.all()],
|
||||||
widget=forms.SelectMultiple(
|
widget=forms.SelectMultiple(
|
||||||
attrs={
|
attrs={
|
||||||
'class': 'select2',
|
'class': 'select2',
|
||||||
|
@ -134,18 +144,26 @@ class UserBulkUpdateForm(forms.ModelForm):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = User
|
model = User
|
||||||
fields = ['users', 'role', 'groups', 'date_expired', 'is_active', 'enable_otp']
|
fields = ['users', 'role', 'groups', 'date_expired', 'is_active']
|
||||||
widgets = {
|
widgets = {
|
||||||
'groups': forms.SelectMultiple(
|
"groups": forms.SelectMultiple(
|
||||||
attrs={'class': 'select2',
|
attrs={
|
||||||
'data-placeholder': _('Select user groups')}),
|
'class': 'select2',
|
||||||
|
'data-placeholder': _('Select users')
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
def save(self, commit=True):
|
def save(self, commit=True):
|
||||||
cleaned_data = {k: v for k, v in self.cleaned_data.items() if
|
changed_fields = []
|
||||||
v is not None}
|
for field in self._meta.fields:
|
||||||
users_id = cleaned_data.pop('users')
|
if self.data.get(field) is not None:
|
||||||
groups = cleaned_data.pop('groups')
|
changed_fields.append(field)
|
||||||
|
|
||||||
|
cleaned_data = {k: v for k, v in self.cleaned_data.items()
|
||||||
|
if k in changed_fields}
|
||||||
|
users_id = cleaned_data.pop('users', '')
|
||||||
|
groups = cleaned_data.pop('groups', [])
|
||||||
users = User.objects.filter(id__in=users_id)
|
users = User.objects.filter(id__in=users_id)
|
||||||
users.update(**cleaned_data)
|
users.update(**cleaned_data)
|
||||||
if groups:
|
if groups:
|
||||||
|
@ -155,42 +173,42 @@ class UserBulkUpdateForm(forms.ModelForm):
|
||||||
|
|
||||||
|
|
||||||
class UserGroupForm(forms.ModelForm):
|
class UserGroupForm(forms.ModelForm):
|
||||||
|
users = forms.ModelMultipleChoiceField(
|
||||||
|
queryset=User.objects.all(),
|
||||||
|
widget=forms.SelectMultiple(
|
||||||
|
attrs={
|
||||||
|
'class': 'select2',
|
||||||
|
'data-placeholder': _('Select users')
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
instance = kwargs.get('instance')
|
||||||
|
if instance:
|
||||||
|
initial = kwargs.get('initial', {})
|
||||||
|
initial.update({
|
||||||
|
'users': instance.users.all(),
|
||||||
|
})
|
||||||
|
kwargs['initial'] = initial
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
|
def save(self, commit=True):
|
||||||
|
group = super().save(commit=commit)
|
||||||
|
users = self.cleaned_data['users']
|
||||||
|
group.users.set(users)
|
||||||
|
return group
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = UserGroup
|
model = UserGroup
|
||||||
fields = [
|
fields = [
|
||||||
'name', 'comment'
|
'name', 'users', 'comment'
|
||||||
]
|
]
|
||||||
help_texts = {
|
help_texts = {
|
||||||
'name': '* required'
|
'name': '* required'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class UserPrivateAssetPermissionForm(forms.ModelForm):
|
|
||||||
def save(self, commit=True):
|
|
||||||
self.instance = super(UserPrivateAssetPermissionForm, self)\
|
|
||||||
.save(commit=commit)
|
|
||||||
self.instance.users = [self.user]
|
|
||||||
self.instance.save()
|
|
||||||
return self.instance
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = AssetPermission
|
|
||||||
fields = [
|
|
||||||
'assets', 'asset_groups', 'system_users', 'name',
|
|
||||||
]
|
|
||||||
widgets = {
|
|
||||||
'assets': forms.SelectMultiple(
|
|
||||||
attrs={'class': 'select2',
|
|
||||||
'data-placeholder': _('Select assets')}),
|
|
||||||
'asset_groups': forms.SelectMultiple(
|
|
||||||
attrs={'class': 'select2',
|
|
||||||
'data-placeholder': _('Select asset groups')}),
|
|
||||||
'system_users': forms.SelectMultiple(
|
|
||||||
attrs={'class': 'select2',
|
|
||||||
'data-placeholder': _('Select system users')}),
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class UserGroupPrivateAssetPermissionForm(forms.ModelForm):
|
class UserGroupPrivateAssetPermissionForm(forms.ModelForm):
|
||||||
def save(self, commit=True):
|
def save(self, commit=True):
|
||||||
self.instance = super(UserGroupPrivateAssetPermissionForm, self)\
|
self.instance = super(UserGroupPrivateAssetPermissionForm, self)\
|
||||||
|
|
|
@ -69,44 +69,3 @@ class UserGroupUpdateMemeberSerializer(serializers.ModelSerializer):
|
||||||
model = UserGroup
|
model = UserGroup
|
||||||
fields = ['id', 'users']
|
fields = ['id', 'users']
|
||||||
|
|
||||||
|
|
||||||
# class GroupDetailSerializer(serializers.ModelSerializer):
|
|
||||||
# class Meta:
|
|
||||||
# model = UserGroup
|
|
||||||
# fields = ['id', 'name', 'comment', 'date_created', 'created_by', 'users']
|
|
||||||
|
|
||||||
|
|
||||||
# class UserBulkUpdateSerializer(BulkSerializerMixin, serializers.ModelSerializer):
|
|
||||||
# group_display = serializers.SerializerMethodField()
|
|
||||||
# active_display = serializers.SerializerMethodField()
|
|
||||||
# groups = serializers.PrimaryKeyRelatedField(many=True, queryset=UserGroup.objects.all())
|
|
||||||
#
|
|
||||||
# class Meta(object):
|
|
||||||
# model = User
|
|
||||||
# list_serializer_class = BulkListSerializer
|
|
||||||
# fields = ['id', 'is_active', 'username', 'name', 'email', 'role', 'avatar',
|
|
||||||
# 'enable_otp', 'comment', 'groups', 'get_role_display',
|
|
||||||
# 'group_display', 'active_display']
|
|
||||||
#
|
|
||||||
# @staticmethod
|
|
||||||
# def get_group_display(obj):
|
|
||||||
# return " ".join([group.name for group in obj.groups.all()])
|
|
||||||
#
|
|
||||||
# @staticmethod
|
|
||||||
# def get_active_display(obj):
|
|
||||||
# TODO: user active state
|
|
||||||
# return not (obj.is_expired and obj.is_active)
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# class GroupBulkUpdateSerializer(BulkSerializerMixin, serializers.ModelSerializer):
|
|
||||||
# user_amount = serializers.SerializerMethodField()
|
|
||||||
#
|
|
||||||
# class Meta:
|
|
||||||
# model = UserGroup
|
|
||||||
# list_serializer_class = BulkListSerializer
|
|
||||||
# fields = ['id', 'name', 'comment', 'user_amount']
|
|
||||||
#
|
|
||||||
# @staticmethod
|
|
||||||
# def get_user_amount(obj):
|
|
||||||
# return obj.users.count()
|
|
||||||
#
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ from django.dispatch import Signal, receiver
|
||||||
from common.utils import get_logger
|
from common.utils import get_logger
|
||||||
|
|
||||||
logger = get_logger(__file__)
|
logger = get_logger(__file__)
|
||||||
on_user_created = Signal(providing_args=['user'])
|
on_user_created = Signal(providing_args=['user', 'request'])
|
||||||
|
|
||||||
|
|
||||||
@receiver(on_user_created)
|
@receiver(on_user_created)
|
||||||
|
|
|
@ -32,12 +32,12 @@
|
||||||
<span class="help-block ">{{ form.date_expired.errors }}</span>
|
<span class="help-block ">{{ form.date_expired.errors }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
{# <div class="form-group">#}
|
||||||
<label for="{{ form.enable_otp.id_for_label }}" class="col-sm-2 control-label">{% trans 'Enable OTP' %}</label>
|
{# <label for="{{ form.enable_otp.id_for_label }}" class="col-sm-2 control-label">{% trans 'Enable OTP' %}</label>#}
|
||||||
<div class="col-sm-8">
|
{# <div class="col-sm-8">#}
|
||||||
{{ form.enable_otp }}
|
{# {{ form.enable_otp }}#}
|
||||||
</div>
|
{# </div>#}
|
||||||
</div>
|
{# </div>#}
|
||||||
<div class="hr-line-dashed"></div>
|
<div class="hr-line-dashed"></div>
|
||||||
<h3>{% trans 'Profile' %}</h3>
|
<h3>{% trans 'Profile' %}</h3>
|
||||||
{% bootstrap_field form.phone layout="horizontal" %}
|
{% bootstrap_field form.phone layout="horizontal" %}
|
||||||
|
|
|
@ -1,182 +0,0 @@
|
||||||
{% extends 'base.html' %}
|
|
||||||
{% load bootstrap3 %}
|
|
||||||
{% load static %}
|
|
||||||
{% load i18n %}
|
|
||||||
|
|
||||||
{% block custom_head_css_js %}
|
|
||||||
<link href="{% static "css/plugins/select2/select2.min.css" %}" rel="stylesheet">
|
|
||||||
<script src="{% static "js/plugins/select2/select2.full.min.js" %}"></script>
|
|
||||||
{% endblock %}
|
|
||||||
{% block content %}
|
|
||||||
<div class="wrapper wrapper-content animated fadeInRight">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm-12">
|
|
||||||
<div class="ibox float-e-margins">
|
|
||||||
<div class="panel-options">
|
|
||||||
<ul class="nav nav-tabs">
|
|
||||||
<li>
|
|
||||||
<a href="{% url 'users:user-detail' pk=user.id %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'User detail' %} </a>
|
|
||||||
</li>
|
|
||||||
<li class="active">
|
|
||||||
<a href="{% url 'users:user-asset-permission' pk=user.id %}" class="text-center"><i class="fa fa-bar-chart-o"></i> {% trans 'Asset permission' %}</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="{% url 'users:user-granted-asset' pk=user.id %}" class="text-center"><i class="fa fa-cubes"></i> {% trans 'Asset granted' %}</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="tab-content">
|
|
||||||
<div class="col-sm-8" style="padding-left: 0;">
|
|
||||||
<div class="ibox float-e-margins">
|
|
||||||
<div class="ibox-title">
|
|
||||||
<span style="float: left">{% trans 'Asset permission of ' %} <b>{{ user.name }}</b></span>
|
|
||||||
<div class="ibox-tools">
|
|
||||||
<a class="collapse-link">
|
|
||||||
<i class="fa fa-chevron-up"></i>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
|
||||||
<i class="fa fa-wrench"></i>
|
|
||||||
</a>
|
|
||||||
<ul class="dropdown-menu dropdown-user">
|
|
||||||
</ul>
|
|
||||||
<a class="close-link">
|
|
||||||
<i class="fa fa-times"></i>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="ibox-content">
|
|
||||||
<table class="table table-hover " id="user_permissions_table" >
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th class="text-center">
|
|
||||||
<input type="checkbox" id="check_all" class="ipt_check_all" >
|
|
||||||
</th>
|
|
||||||
<th>{% trans 'Name' %}</th>
|
|
||||||
<th>{% trans 'Asset' %}</th>
|
|
||||||
<th>{% trans 'Asset group' %}</th>
|
|
||||||
<th>{% trans 'System user' %}</th>
|
|
||||||
<th>{% trans 'Valid' %}</th>
|
|
||||||
<th></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-4" style="padding-left: 0;padding-right: 0">
|
|
||||||
<div class="panel panel-primary">
|
|
||||||
<div class="panel-heading">
|
|
||||||
<i class="fa fa-info-circle"></i> {% trans 'Quick create permission for user' %}
|
|
||||||
</div>
|
|
||||||
<div class="panel-body">
|
|
||||||
<form method="post" action="{% url 'users:user-asset-permission-create' pk=user.id %}">
|
|
||||||
<table class="table">
|
|
||||||
<tbody>
|
|
||||||
{% csrf_token %}
|
|
||||||
<tr class="no-borders-tr">
|
|
||||||
<td colspan="1" style="padding-top: 0">
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="no-borders-tr">
|
|
||||||
<td colspan="1" style="padding-top: 0">
|
|
||||||
{% bootstrap_field form.assets %}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="no-borders-tr">
|
|
||||||
<td colspan="1" style="padding-top: 0">
|
|
||||||
{% bootstrap_field form.asset_groups %}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="no-borders-tr">
|
|
||||||
<td colspan="1" style="padding-top: 0">
|
|
||||||
{% bootstrap_field form.system_users %}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="no-borders-tr">
|
|
||||||
<td>
|
|
||||||
<button type="submit" class="btn btn-primary btn-sm">{% trans 'Submit' %}</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
{% block custom_foot_js %}
|
|
||||||
<script>
|
|
||||||
$(document).ready(function () {
|
|
||||||
$('.select2').select2();
|
|
||||||
var options = {
|
|
||||||
ele: $('#user_permissions_table'),
|
|
||||||
buttons: [],
|
|
||||||
order: [],
|
|
||||||
select: [],
|
|
||||||
columnDefs: [
|
|
||||||
{targets: 1, createdCell: function (td, cellData, rowData) {
|
|
||||||
var detail_btn = '<a href="{% url "perms:asset-permission-detail" pk=DEFAULT_PK %}">' + cellData + '</a>';
|
|
||||||
$(td).html(detail_btn.replace('{{ DEFAULT_PK }}', rowData.id));
|
|
||||||
}},
|
|
||||||
{targets: 2, createdCell: function (td, cellData, rowData) {
|
|
||||||
var dataLength = cellData.length;
|
|
||||||
$(td).html(dataLength);
|
|
||||||
}},
|
|
||||||
{targets: 3, createdCell: function (td, cellData, rowData) {
|
|
||||||
var dataLength = cellData.length;
|
|
||||||
$(td).html(dataLength);
|
|
||||||
}},
|
|
||||||
{targets: 4, createdCell: function (td, cellData, rowData) {
|
|
||||||
var dataLength = cellData.length;
|
|
||||||
$(td).html(dataLength);
|
|
||||||
}},
|
|
||||||
{targets: 5, createdCell: function (td, cellData) {
|
|
||||||
if (!cellData) {
|
|
||||||
$(td).html('<i class="fa fa-times text-danger"></i>')
|
|
||||||
} else {
|
|
||||||
$(td).html('<i class="fa fa-check text-navy"></i>')
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
{targets: 6, createdCell: function (td, cellData, rowData) {
|
|
||||||
var btn = '<button class="btn btn-danger btn-xs btn_del_permission disabled" id="{{ DEFAULT_PK }}" type="button" style="float: right;"><i class="fa fa-minus"></i></button>';
|
|
||||||
if (rowData.is_inherited) {
|
|
||||||
$(td).html(btn)
|
|
||||||
} else {
|
|
||||||
btn = btn.replace('{{ DEFAULT_PK }}', cellData);
|
|
||||||
$(td).html(btn.replace('disabled', ''));
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
],
|
|
||||||
ajax_url: '{% url "api-perms:asset-permission-list" %}?user={{ user.id }}',
|
|
||||||
columns: [{data: function(){return ""}}, {data: "name" }, {data: "assets" }, {data: "asset_groups"},
|
|
||||||
{data: "system_users"}, {data: "is_active"}, {data: "id"}]
|
|
||||||
};
|
|
||||||
jumpserver.initDataTable(options);
|
|
||||||
}).on('click', '.btn_del_permission', function () {
|
|
||||||
var $this = $(this);
|
|
||||||
var body = {
|
|
||||||
id: $this.attr('id'),
|
|
||||||
user_id: {{ user.id }}
|
|
||||||
};
|
|
||||||
var the_url = "{% url 'api-perms:revoke-user-asset-permission' %}";
|
|
||||||
var success = function () {
|
|
||||||
$this.closest('tr').remove();
|
|
||||||
};
|
|
||||||
APIUpdateAttr({
|
|
||||||
url: the_url,
|
|
||||||
body: JSON.stringify(body),
|
|
||||||
method: 'PUT',
|
|
||||||
success_message: '{% trans "Revoke Successfully!" %}',
|
|
||||||
success: success
|
|
||||||
});
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
{% endblock %}
|
|
|
@ -6,7 +6,7 @@
|
||||||
{# {% bootstrap_field form.username layout="horizontal" %}#}
|
{# {% bootstrap_field form.username layout="horizontal" %}#}
|
||||||
{#{% endblock %}#}
|
{#{% endblock %}#}
|
||||||
{% block password %}
|
{% block password %}
|
||||||
<h3>{% trans 'Password' %}</h3>
|
<h3>{% trans 'Auth' %}</h3>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-sm-2 control-label">{% trans 'Password' %}</label>
|
<label class="col-sm-2 control-label">{% trans 'Password' %}</label>
|
||||||
<div class="col-sm-8 controls" >
|
<div class="col-sm-8 controls" >
|
||||||
|
|
|
@ -18,9 +18,6 @@
|
||||||
<li class="active">
|
<li class="active">
|
||||||
<a href="{% url 'users:user-detail' pk=user_object.id %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'User detail' %} </a>
|
<a href="{% url 'users:user-detail' pk=user_object.id %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'User detail' %} </a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
|
||||||
<a href="{% url 'users:user-asset-permission' pk=user_object.id %}" class="text-center"><i class="fa fa-bar-chart-o"></i> {% trans 'Asset permission' %}</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url 'users:user-granted-asset' pk=user_object.id %}" class="text-center"><i class="fa fa-cubes"></i> {% trans 'Asset granted' %}</a>
|
<a href="{% url 'users:user-granted-asset' pk=user_object.id %}" class="text-center"><i class="fa fa-cubes"></i> {% trans 'Asset granted' %}</a>
|
||||||
</li>
|
</li>
|
||||||
|
@ -35,7 +32,7 @@
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-content">
|
<div class="tab-content">
|
||||||
<div class="col-sm-7" style="padding-left: 0">
|
<div class="col-sm-8" style="padding-left: 0">
|
||||||
<div class="ibox float-e-margins">
|
<div class="ibox float-e-margins">
|
||||||
<div class="ibox-title">
|
<div class="ibox-title">
|
||||||
<span class="label"><b>{{ user_object.name }}</b></span>
|
<span class="label"><b>{{ user_object.name }}</b></span>
|
||||||
|
@ -118,7 +115,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-5" style="padding-left: 0;padding-right: 0">
|
<div class="col-sm-4" style="padding-left: 0;padding-right: 0">
|
||||||
<div class="panel panel-primary">
|
<div class="panel panel-primary">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<i class="fa fa-info-circle"></i> {% trans 'Quick modify' %}
|
<i class="fa fa-info-circle"></i> {% trans 'Quick modify' %}
|
||||||
|
@ -140,34 +137,34 @@
|
||||||
</div>
|
</div>
|
||||||
</span></td>
|
</span></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{# <tr>#}
|
||||||
|
{# <td>{% trans 'Enable OTP' %}:</td>#}
|
||||||
|
{# <td><span class="pull-right">#}
|
||||||
|
{# <div class="switch">#}
|
||||||
|
{# <div class="onoffswitch">#}
|
||||||
|
{# <input type="checkbox" class="onoffswitch-checkbox" {% if user_object.enable_otp %} checked {% endif %}#}
|
||||||
|
{# id="enable_otp">#}
|
||||||
|
{# <label class="onoffswitch-label" for="enable_otp">#}
|
||||||
|
{# <span class="onoffswitch-inner"></span>#}
|
||||||
|
{# <span class="onoffswitch-switch"></span>#}
|
||||||
|
{# </label>#}
|
||||||
|
{# </div>#}
|
||||||
|
{# </div>#}
|
||||||
|
{# </span></td>#}
|
||||||
|
{# </tr>#}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{% trans 'Enable OTP' %}:</td>
|
<td>{% trans 'Send reset password mail' %}:</td>
|
||||||
<td><span class="pull-right">
|
|
||||||
<div class="switch">
|
|
||||||
<div class="onoffswitch">
|
|
||||||
<input type="checkbox" class="onoffswitch-checkbox" {% if user_object.enable_otp %} checked {% endif %}
|
|
||||||
id="enable_otp">
|
|
||||||
<label class="onoffswitch-label" for="enable_otp">
|
|
||||||
<span class="onoffswitch-inner"></span>
|
|
||||||
<span class="onoffswitch-switch"></span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</span></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>{% trans 'Reset password' %}:</td>
|
|
||||||
<td>
|
<td>
|
||||||
<span class="pull-right">
|
<span class="pull-right">
|
||||||
<button type="button" class="btn btn-primary btn-xs" id="btn_reset_password" style="width: 54px">{% trans 'Reset' %}</button>
|
<button type="button" class="btn btn-primary btn-xs" id="btn_reset_password" style="width: 54px">{% trans 'Send' %}</button>
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>{% trans 'Reset ssh key' %}:</td>
|
<td>{% trans 'Send reset ssh key mail' %}:</td>
|
||||||
<td>
|
<td>
|
||||||
<span class="pull-right">
|
<span class="pull-right">
|
||||||
<button type="button" class="btn btn-primary btn-xs" id="btn_reset_pk" style="width: 54px;">{% trans 'Reset' %}</button>
|
<button type="button" class="btn btn-primary btn-xs" id="btn_reset_pk" style="width: 54px;">{% trans 'Send' %}</button>
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -188,7 +185,7 @@
|
||||||
<td colspan="2" class="no-borders">
|
<td colspan="2" class="no-borders">
|
||||||
<select data-placeholder="{% trans 'Join user groups' %}" id="groups_selected" class="select2" style="width: 100%" multiple="" tabindex="4">
|
<select data-placeholder="{% trans 'Join user groups' %}" id="groups_selected" class="select2" style="width: 100%" multiple="" tabindex="4">
|
||||||
{% for group in groups %}
|
{% for group in groups %}
|
||||||
<option value="{{ group.id }}" id="opt_{{ group.id }}">{{ group.name }}</option>
|
<option value="{{ group.id }}" id="opt_{{ group.id }}" >{{ group.name }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
|
@ -263,7 +260,7 @@ $(document).ready(function() {
|
||||||
})
|
})
|
||||||
.on('select2:unselect', function(evt) {
|
.on('select2:unselect', function(evt) {
|
||||||
var data = evt.params.data;
|
var data = evt.params.data;
|
||||||
delete jumpserver.groups_selected[data.id]
|
delete jumpserver.groups_selected[data.id];
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.on('click', '#is_active', function() {
|
.on('click', '#is_active', function() {
|
||||||
|
@ -279,20 +276,20 @@ $(document).ready(function() {
|
||||||
success_message: success
|
success_message: success
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.on('click', '#enable_otp', function() {
|
{#.on('click', '#enable_otp', function() {#}
|
||||||
var the_url = "{% url 'api-users:user-detail' pk=user_object.id %}";
|
{# var the_url = "{% url 'api-users:user-detail' pk=user_object.id %}";#}
|
||||||
var checked = $(this).prop('checked');
|
{# var checked = $(this).prop('checked');#}
|
||||||
var body = {
|
{# var body = {#}
|
||||||
'enable_otp': checked
|
{# 'enable_otp': checked#}
|
||||||
};
|
{# };#}
|
||||||
var success = '{% trans "Update successfully!" %}';
|
{# var success = '{% trans "Update successfully!" %}';#}
|
||||||
APIUpdateAttr({
|
{# APIUpdateAttr({#}
|
||||||
url: the_url,
|
{# url: the_url,#}
|
||||||
body: JSON.stringify(body),
|
{# body: JSON.stringify(body),#}
|
||||||
success_message: success
|
{# success_message: success#}
|
||||||
});
|
{# });#}
|
||||||
})
|
{# });#}
|
||||||
.on('click', '#btn_join_group', function() {
|
.on('click', '#btn_join_group', function() {
|
||||||
if (Object.keys(jumpserver.groups_selected).length === 0) {
|
if (Object.keys(jumpserver.groups_selected).length === 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -300,7 +297,7 @@ $(document).ready(function() {
|
||||||
return $(this).data('gid');
|
return $(this).data('gid');
|
||||||
}).get();
|
}).get();
|
||||||
$.map(jumpserver.groups_selected, function(value, index) {
|
$.map(jumpserver.groups_selected, function(value, index) {
|
||||||
groups.push(parseInt(index));
|
groups.push(index);
|
||||||
$('#opt_' + index).remove();
|
$('#opt_' + index).remove();
|
||||||
});
|
});
|
||||||
updateUserGroups(groups)
|
updateUserGroups(groups)
|
||||||
|
@ -368,7 +365,7 @@ $(document).ready(function() {
|
||||||
}, function() {
|
}, function() {
|
||||||
doReset();
|
doReset();
|
||||||
});
|
});
|
||||||
}).on('click', '#btn_user_update_pk', function(){
|
}).on('click', '#btn-user-update-pk', function(){
|
||||||
var $this = $(this);
|
var $this = $(this);
|
||||||
var pk = $('#txt_pk').val();
|
var pk = $('#txt_pk').val();
|
||||||
var the_url = '{% url "api-users:user-public-key-reset" pk=user.id %}';
|
var the_url = '{% url "api-users:user-public-key-reset" pk=user.id %}';
|
||||||
|
|
|
@ -17,9 +17,6 @@
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url 'users:user-detail' pk=user.id %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'User detail' %} </a>
|
<a href="{% url 'users:user-detail' pk=user.id %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'User detail' %} </a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
|
||||||
<a href="{% url 'users:user-asset-permission' pk=user.id %}" class="text-center"><i class="fa fa-bar-chart-o"></i> {% trans 'Asset permission' %}</a>
|
|
||||||
</li>
|
|
||||||
<li class="active">
|
<li class="active">
|
||||||
<a href="{% url 'users:user-granted-asset' pk=user.id %}" class="text-center"><i class="fa fa-cubes"></i> {% trans 'Asset granted' %}</a>
|
<a href="{% url 'users:user-granted-asset' pk=user.id %}" class="text-center"><i class="fa fa-cubes"></i> {% trans 'Asset granted' %}</a>
|
||||||
</li>
|
</li>
|
||||||
|
@ -48,12 +45,9 @@
|
||||||
<table class="table table-hover " id="user_assets_table" >
|
<table class="table table-hover " id="user_assets_table" >
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="text-center"></th>
|
|
||||||
<th>{% trans 'Hostname' %}</th>
|
<th>{% trans 'Hostname' %}</th>
|
||||||
<th>{% trans 'IP' %}</th>
|
<th>{% trans 'IP' %}</th>
|
||||||
<th>{% trans 'Port' %}</th>
|
|
||||||
<th>{% trans 'System user' %}</th>
|
<th>{% trans 'System user' %}</th>
|
||||||
<th>{% trans 'Valid' %}</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@ -84,7 +78,6 @@
|
||||||
<table class="table table-hover" id="user_asset_groups_table" >
|
<table class="table table-hover" id="user_asset_groups_table" >
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th></th>
|
|
||||||
<th>{% trans 'Name' %}</th>
|
<th>{% trans 'Name' %}</th>
|
||||||
<th>{% trans 'Asset' %}</th>
|
<th>{% trans 'Asset' %}</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -112,28 +105,15 @@
|
||||||
order: [],
|
order: [],
|
||||||
select: [],
|
select: [],
|
||||||
columnDefs: [
|
columnDefs: [
|
||||||
{targets: 1, createdCell: function (td, cellData, rowData) {
|
{targets: 0, createdCell: function (td, cellData, rowData) {
|
||||||
var detail_btn = '<a href="{% url "assets:asset-detail" pk=DEFAULT_PK %}">' + cellData + '</a>';
|
var detail_btn = '<a href="{% url "assets:asset-detail" pk=DEFAULT_PK %}">' + cellData + '</a>';
|
||||||
$(td).html(detail_btn.replace('{{ DEFAULT_PK }}', rowData.id));
|
$(td).html(detail_btn.replace('{{ DEFAULT_PK }}', rowData.id));
|
||||||
}},
|
|
||||||
{targets: 4, createdCell: function (td, cellData, rowData) {
|
|
||||||
if (cellData.length > 10){
|
|
||||||
$(td).html(cellData.substring(1, 10) + '..')
|
|
||||||
} else {
|
|
||||||
$(td).html(cellData)
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
{targets: 5, createdCell: function (td, cellData) {
|
|
||||||
if (!cellData) {
|
|
||||||
$(td).html('<i class="fa fa-times text-danger"></i>')
|
|
||||||
} else {
|
|
||||||
$(td).html('<i class="fa fa-check text-navy"></i>')
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
],
|
],
|
||||||
ajax_url: '{% url "api-perms:user-assets" pk=user.id %}',
|
ajax_url: '{% url "api-perms:user-assets" pk=user.id %}',
|
||||||
columns: [{data: function(){return ""}}, {data: "hostname" }, {data: "ip" }, {data: "port"},
|
columns: [{data: "hostname" }, {data: "ip" },
|
||||||
{data: "system_users_join"}, {data: "is_active"}]
|
{data: "system_users_join"}
|
||||||
|
]
|
||||||
};
|
};
|
||||||
var options2 = {
|
var options2 = {
|
||||||
ele: $('#user_asset_groups_table'),
|
ele: $('#user_asset_groups_table'),
|
||||||
|
@ -141,13 +121,14 @@
|
||||||
order: [],
|
order: [],
|
||||||
select: [],
|
select: [],
|
||||||
columnDefs: [
|
columnDefs: [
|
||||||
{targets: 1, createdCell: function (td, cellData, rowData) {
|
{targets: 0, createdCell: function (td, cellData, rowData) {
|
||||||
var detail_btn = '<a href="{% url "assets:asset-group-detail" pk=DEFAULT_PK %}">' + cellData + '</a>';
|
var detail_btn = '<a href="{% url "assets:asset-group-detail" pk=DEFAULT_PK %}">' + cellData + '</a>';
|
||||||
$(td).html(detail_btn.replace('{{ DEFAULT_PK }}', rowData.id));
|
$(td).html(detail_btn.replace('{{ DEFAULT_PK }}', rowData.id));
|
||||||
}}
|
}}
|
||||||
],
|
],
|
||||||
ajax_url: '{% url "api-perms:user-asset-groups" pk=user.id %}',
|
ajax_url: '{% url "api-perms:user-asset-groups" pk=user.id %}',
|
||||||
columns: [{data: function(){return ""}}, {data: "name" }, {data: "assets_amount" }]
|
columns: [{data: "name" }, {data: "assets_amount" }],
|
||||||
|
paging: false
|
||||||
};
|
};
|
||||||
jumpserver.initDataTable(options);
|
jumpserver.initDataTable(options);
|
||||||
jumpserver.initDataTable(options2);
|
jumpserver.initDataTable(options2);
|
||||||
|
|
|
@ -1,181 +0,0 @@
|
||||||
{% extends 'base.html' %}
|
|
||||||
{% load bootstrap3 %}
|
|
||||||
{% load static %}
|
|
||||||
{% load i18n %}
|
|
||||||
|
|
||||||
{% block custom_head_css_js %}
|
|
||||||
<link href="{% static "css/plugins/select2/select2.min.css" %}" rel="stylesheet">
|
|
||||||
<script src="{% static "js/plugins/select2/select2.full.min.js" %}"></script>
|
|
||||||
{% endblock %}
|
|
||||||
{% block content %}
|
|
||||||
<div class="wrapper wrapper-content animated fadeInRight">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm-12">
|
|
||||||
<div class="ibox float-e-margins">
|
|
||||||
<div class="panel-options">
|
|
||||||
<ul class="nav nav-tabs">
|
|
||||||
<li>
|
|
||||||
<a href="{% url 'users:user-group-detail' pk=user_group.id %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'User detail' %} </a>
|
|
||||||
</li>
|
|
||||||
<li class="active">
|
|
||||||
<a href="{% url 'users:user-group-asset-permission' pk=user_group.id %}" class="text-center"><i class="fa fa-bar-chart-o"></i> {% trans 'Asset permission' %}</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="{% url 'users:user-group-granted-asset' pk=user_group.id %}" class="text-center"><i class="fa fa-cubes"></i> {% trans 'Asset granted' %}</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="tab-content">
|
|
||||||
<div class="col-sm-7" style="padding-left: 0;">
|
|
||||||
<div class="ibox float-e-margins">
|
|
||||||
<div class="ibox-title">
|
|
||||||
<span style="float: left">{% trans 'Asset permission of ' %} <b>{{ user_group.name }}</b></span>
|
|
||||||
<div class="ibox-tools">
|
|
||||||
<a class="collapse-link">
|
|
||||||
<i class="fa fa-chevron-up"></i>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
|
||||||
<i class="fa fa-wrench"></i>
|
|
||||||
</a>
|
|
||||||
<ul class="dropdown-menu dropdown-user">
|
|
||||||
</ul>
|
|
||||||
<a class="close-link">
|
|
||||||
<i class="fa fa-times"></i>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="ibox-content">
|
|
||||||
<table class="table table-hover " id="user_group_permissions_table" >
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th class="text-center">
|
|
||||||
<input type="checkbox" id="check_all" class="ipt_check_all" >
|
|
||||||
</th>
|
|
||||||
<th>{% trans 'Name' %}</th>
|
|
||||||
<th>{% trans 'Asset' %}</th>
|
|
||||||
<th>{% trans 'Asset group' %}</th>
|
|
||||||
<th>{% trans 'System user' %}</th>
|
|
||||||
<th>{% trans 'Valid' %}</th>
|
|
||||||
<th></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-5" style="padding-left: 0;padding-right: 0">
|
|
||||||
<div class="panel panel-primary">
|
|
||||||
<div class="panel-heading">
|
|
||||||
<i class="fa fa-info-circle"></i> {% trans 'Quick create permission for user group' %}
|
|
||||||
</div>
|
|
||||||
<div class="panel-body">
|
|
||||||
<form method="post" action="{% url 'users:user-group-asset-permission-create' pk=user_group.id %}">
|
|
||||||
<table class="table">
|
|
||||||
<tbody>
|
|
||||||
{% csrf_token %}
|
|
||||||
<tr class="no-borders-tr">
|
|
||||||
<td colspan="1" style="padding-top: 0">
|
|
||||||
{% bootstrap_field form.name %}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="no-borders-tr">
|
|
||||||
<td colspan="1" style="padding-top: 0">
|
|
||||||
{% bootstrap_field form.assets %}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="no-borders-tr">
|
|
||||||
<td colspan="1" style="padding-top: 0">
|
|
||||||
{% bootstrap_field form.asset_groups %}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="no-borders-tr">
|
|
||||||
<td colspan="1" style="padding-top: 0">
|
|
||||||
{% bootstrap_field form.system_users %}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="no-borders-tr">
|
|
||||||
<td>
|
|
||||||
<button type="submit" class="btn btn-primary btn-sm">{% trans 'Submit' %}</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
{% block custom_foot_js %}
|
|
||||||
<script>
|
|
||||||
$(document).ready(function () {
|
|
||||||
$('.select2').select2();
|
|
||||||
var options = {
|
|
||||||
ele: $('#user_group_permissions_table'),
|
|
||||||
buttons: [],
|
|
||||||
order: [],
|
|
||||||
select: [],
|
|
||||||
columnDefs: [
|
|
||||||
{targets: 1, createdCell: function (td, cellData, rowData) {
|
|
||||||
var detail_btn = '<a href="{% url "perms:asset-permission-detail" pk=DEFAULT_PK %}">' + cellData + '</a>';
|
|
||||||
$(td).html(detail_btn.replace('{{ DEFAULT_PK }}', rowData.id));
|
|
||||||
}},
|
|
||||||
{targets: 2, createdCell: function (td, cellData, rowData) {
|
|
||||||
var dataLength = cellData.length;
|
|
||||||
$(td).html(dataLength);
|
|
||||||
}},
|
|
||||||
{targets: 3, createdCell: function (td, cellData, rowData) {
|
|
||||||
var dataLength = cellData.length;
|
|
||||||
$(td).html(dataLength);
|
|
||||||
}},
|
|
||||||
{targets: 4, createdCell: function (td, cellData, rowData) {
|
|
||||||
var dataLength = cellData.length;
|
|
||||||
$(td).html(dataLength);
|
|
||||||
}},
|
|
||||||
{targets: 5, createdCell: function (td, cellData) {
|
|
||||||
if (!cellData) {
|
|
||||||
$(td).html('<i class="fa fa-times text-danger"></i>')
|
|
||||||
} else {
|
|
||||||
$(td).html('<i class="fa fa-check text-navy"></i>')
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
{targets: 6, createdCell: function (td, cellData, rowData) {
|
|
||||||
var btn = '<button class="btn btn-danger btn-xs btn_del_permission" id="{{ DEFAULT_PK }}" type="button" style="float: right;"><i class="fa fa-minus"></i></button>';
|
|
||||||
btn = btn.replace('{{ DEFAULT_PK }}', cellData);
|
|
||||||
$(td).html(btn)
|
|
||||||
}}
|
|
||||||
],
|
|
||||||
ajax_url: '{% url "api-perms:asset-permission-list" %}?user_group={{ user_group.id }}',
|
|
||||||
columns: [{data: function(){return ""}}, {data: "name" }, {data: "assets" }, {data: "asset_groups"},
|
|
||||||
{data: "system_users"}, {data: "is_active"}, {data: "id"}]
|
|
||||||
};
|
|
||||||
jumpserver.initDataTable(options);
|
|
||||||
}).on('click', '.btn_del_permission', function () {
|
|
||||||
var $this = $(this);
|
|
||||||
var body = {
|
|
||||||
id: $this.attr('id'),
|
|
||||||
user_group_id: {{ user_group.id }}
|
|
||||||
};
|
|
||||||
var the_url = "{% url 'api-perms:revoke-user-group-asset-permission' %}";
|
|
||||||
var success = function () {
|
|
||||||
$this.closest('tr').remove();
|
|
||||||
};
|
|
||||||
APIUpdateAttr({
|
|
||||||
url: the_url,
|
|
||||||
body: JSON.stringify(body),
|
|
||||||
method: 'PUT',
|
|
||||||
success_message: '{% trans "Revoke Successfully!" %}',
|
|
||||||
success: success
|
|
||||||
});
|
|
||||||
}).on('click', 'buttons-excel', function () {
|
|
||||||
console.log('click excel')
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
{% endblock %}
|
|
|
@ -24,20 +24,21 @@
|
||||||
<form method="post" class="form-horizontal" action="" >
|
<form method="post" class="form-horizontal" action="" >
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{% bootstrap_field form.name layout="horizontal" %}
|
{% bootstrap_field form.name layout="horizontal" %}
|
||||||
<div class="form-group">
|
{% bootstrap_field form.users layout="horizontal" %}
|
||||||
<label for="users" class="col-sm-2 control-label">{% trans 'Users' %}</label>
|
{# <div class="form-group">#}
|
||||||
<div class="col-sm-9">
|
{# <label for="users" class="col-sm-2 control-label">{% trans 'Users' %}</label>#}
|
||||||
<select name="users" id="id_users" data-placeholder="{% trans 'Select User' %}" class="select2 form-control m-b" multiple tabindex="2">
|
{# <div class="col-sm-9">#}
|
||||||
{% for user in users %}
|
{# <select name="users" id="id_users" data-placeholder="{% trans 'Select User' %}" class="select2 form-control m-b" multiple tabindex="2">#}
|
||||||
{% if user.id in group_users %}
|
{# {% for user in users %}#}
|
||||||
<option value="{{ user.id }}" selected>{{ user.name }}</option>
|
{# {% if user.id in group_users %}#}
|
||||||
{% else %}
|
{# <option value="{{ user.id }}" selected>{{ user.name }}</option>#}
|
||||||
<option value="{{ user.id }}">{{ user.name }}</option>
|
{# {% else %}#}
|
||||||
{% endif %}
|
{# <option value="{{ user.id }}">{{ user.name }}</option>#}
|
||||||
{% endfor %}
|
{# {% endif %}#}
|
||||||
</select>
|
{# {% endfor %}#}
|
||||||
</div>
|
{# </select>#}
|
||||||
</div>
|
{# </div>#}
|
||||||
|
{# </div>#}
|
||||||
{% bootstrap_field form.comment layout="horizontal" %}
|
{% bootstrap_field form.comment layout="horizontal" %}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="col-sm-4 col-sm-offset-2">
|
<div class="col-sm-4 col-sm-offset-2">
|
||||||
|
|
|
@ -22,10 +22,7 @@
|
||||||
<a href="{% url 'users:user-group-detail' pk=user_group.id %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'User group detail' %} </a>
|
<a href="{% url 'users:user-group-detail' pk=user_group.id %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'User group detail' %} </a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url 'users:user-group-asset-permission' pk=user_group.id %}" class="text-center"><i class="fa fa-bar-chart-o"></i> {% trans 'Asset permission' %}</a>
|
<a href="{% url 'users:user-group-granted-asset' pk=user_group.id %}" class="text-center"><i class="fa fa-cubes"></i> {% trans 'Asset granted' %}</a>
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="{% url 'users:user-group-granted-asset' pk=user.id %}" class="text-center"><i class="fa fa-cubes"></i> {% trans 'Asset granted' %}</a>
|
|
||||||
</li>
|
</li>
|
||||||
<li class="pull-right">
|
<li class="pull-right">
|
||||||
<a class="btn btn-outline btn-default" href="{% url 'users:user-group-update' pk=user_group.id %}"><i class="fa fa-edit"></i>Update</a>
|
<a class="btn btn-outline btn-default" href="{% url 'users:user-group-update' pk=user_group.id %}"><i class="fa fa-edit"></i>Update</a>
|
||||||
|
|
|
@ -17,16 +17,13 @@
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url 'users:user-group-detail' pk=user_group.id %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'User detail' %} </a>
|
<a href="{% url 'users:user-group-detail' pk=user_group.id %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'User detail' %} </a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
|
||||||
<a href="{% url 'users:user-group-asset-permission' pk=user_group.id %}" class="text-center"><i class="fa fa-bar-chart-o"></i> {% trans 'Asset permission' %}</a>
|
|
||||||
</li>
|
|
||||||
<li class="active">
|
<li class="active">
|
||||||
<a href="{% url 'users:user-group-granted-asset' pk=user_group.id %}" class="text-center"><i class="fa fa-cubes"></i> {% trans 'Asset granted' %}</a>
|
<a href="{% url 'users:user-group-granted-asset' pk=user_group.id %}" class="text-center"><i class="fa fa-cubes"></i> {% trans 'Asset granted' %}</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-content">
|
<div class="tab-content">
|
||||||
<div class="col-sm-8" style="padding-left: 0;">
|
<div class="col-sm-7" style="padding-left: 0;">
|
||||||
<div class="ibox float-e-margins">
|
<div class="ibox float-e-margins">
|
||||||
<div class="ibox-title">
|
<div class="ibox-title">
|
||||||
<span style="float: left">{% trans 'Assets granted of ' %} <b>{{ user_group.name }}</b></span>
|
<span style="float: left">{% trans 'Assets granted of ' %} <b>{{ user_group.name }}</b></span>
|
||||||
|
@ -62,7 +59,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-4" style="padding-left: 0;padding-right: 0">
|
<div class="col-sm-5" style="padding-left: 0;padding-right: 0">
|
||||||
<div class="ibox float-e-margins">
|
<div class="ibox float-e-margins">
|
||||||
<div class="ibox-title">
|
<div class="ibox-title">
|
||||||
<span style="float: left">{% trans 'Asset groups granted of ' %} <b>{{ user_group.name }}</b></span>
|
<span style="float: left">{% trans 'Asset groups granted of ' %} <b>{{ user_group.name }}</b></span>
|
||||||
|
|
|
@ -16,18 +16,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
</table>
|
</table>
|
||||||
<div id="actions" class="hide">
|
|
||||||
<div class="input-group">
|
|
||||||
<select class="form-control m-b" style="width: auto" id="slct_bulk_update">
|
|
||||||
<option value="delete">{% trans 'Delete selected' %}</option>
|
|
||||||
</select>
|
|
||||||
<div class="input-group-btn pull-left" style="padding-left: 5px;">
|
|
||||||
<button id='btn_bulk_update' style="height: 32px;" class="btn btn-sm btn-primary">
|
|
||||||
{% trans 'Submit' %}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content_bottom_left %}{% endblock %}
|
{% block content_bottom_left %}{% endblock %}
|
||||||
|
@ -57,11 +46,12 @@ $(document).ready(function() {
|
||||||
} else {
|
} else {
|
||||||
$(td).html(update_btn + del_btn)
|
$(td).html(update_btn + del_btn)
|
||||||
}
|
}
|
||||||
}}],
|
}}
|
||||||
|
],
|
||||||
ajax_url: '{% url "api-users:user-group-list" %}',
|
ajax_url: '{% url "api-users:user-group-list" %}',
|
||||||
columns: [{data: function(){return ""}}, {data: "name" }, {data: "user_amount"},
|
columns: [{data: function(){return ""}}, {data: "name" }, {data: "user_amount"},
|
||||||
{data: "comment"}, {data: "id" }],
|
{data: "comment"}, {data: "id" }],
|
||||||
order: [4, 'asc'],
|
order: [],
|
||||||
op_html: $('#actions').html()
|
op_html: $('#actions').html()
|
||||||
};
|
};
|
||||||
jumpserver.initDataTable(options);
|
jumpserver.initDataTable(options);
|
||||||
|
|
|
@ -52,24 +52,8 @@
|
||||||
{% block custom_foot_js %}
|
{% block custom_foot_js %}
|
||||||
<script src="{% static 'js/jquery.form.min.js' %}"></script>
|
<script src="{% static 'js/jquery.form.min.js' %}"></script>
|
||||||
<script>
|
<script>
|
||||||
function changeField(obj, active) {
|
|
||||||
var $this = $(obj);
|
|
||||||
var field_id = $this.data('id');
|
|
||||||
if (!active) {
|
|
||||||
active = $this.attr('value');
|
|
||||||
}
|
|
||||||
if (active == '0') {
|
|
||||||
$this.attr('value', '1').addClass('label-primary');
|
|
||||||
var form_groups = $('#add_form .form-group:not(.abc)');
|
|
||||||
form_groups.filter(':has(#' + field_id + ')').show().find('select,input').prop('disabled', false)
|
|
||||||
} else {
|
|
||||||
$this.attr('value', '0').removeClass('label-primary');
|
|
||||||
var form_groups = $('#add_form .form-group:not(.abc)');
|
|
||||||
form_groups.filter(':has(#' + field_id + ')').hide().find('select,input').prop('disabled', true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderTable() {
|
function initTable() {
|
||||||
var options = {
|
var options = {
|
||||||
ele: $('#user_list_table'),
|
ele: $('#user_list_table'),
|
||||||
columnDefs: [
|
columnDefs: [
|
||||||
|
@ -90,24 +74,30 @@ function renderTable() {
|
||||||
}},
|
}},
|
||||||
{targets: 6, createdCell: function (td, cellData, rowData) {
|
{targets: 6, createdCell: function (td, cellData, rowData) {
|
||||||
var update_btn = '<a href="{% url "users:user-update" pk='00000000-0000-0000-0000-000000000000' %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'.replace('00000000-0000-0000-0000-000000000000', cellData);
|
var update_btn = '<a href="{% url "users:user-update" pk='00000000-0000-0000-0000-000000000000' %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'.replace('00000000-0000-0000-0000-000000000000', cellData);
|
||||||
var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn_user_delete" data-uid="{{ DEFAULT_PK }}" data-name="99991938">{% trans "Delete" %}</a>'
|
|
||||||
|
var del_btn = "";
|
||||||
|
if (rowData.id === 1 || rowData.username === "admin" || rowData.username === "{{ user.username }}") {
|
||||||
|
del_btn = '<a class="btn btn-xs btn-danger m-l-xs" disabled>{% trans "Delete" %}</a>'
|
||||||
.replace('{{ DEFAULT_PK }}', cellData)
|
.replace('{{ DEFAULT_PK }}', cellData)
|
||||||
.replace('99991938', rowData.name);
|
.replace('99991938', rowData.name);
|
||||||
if (rowData.id === 1 || rowData.username == "admin") {
|
|
||||||
$(td).html(update_btn)
|
|
||||||
} else {
|
} else {
|
||||||
$(td).html(update_btn + del_btn)
|
del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn_user_delete" data-uid="{{ DEFAULT_PK }}" data-name="99991938">{% trans "Delete" %}</a>'
|
||||||
|
.replace('{{ DEFAULT_PK }}', cellData)
|
||||||
|
.replace('99991938', rowData.name);
|
||||||
}
|
}
|
||||||
|
$(td).html(update_btn + del_btn)
|
||||||
}}],
|
}}],
|
||||||
ajax_url: '{% url "api-users:user-list" %}',
|
ajax_url: '{% url "api-users:user-list" %}',
|
||||||
columns: [{data: "id"}, {data: "name" }, {data: "username" }, {data: "get_role_display" },
|
columns: [{data: "id"}, {data: "name" }, {data: "username" }, {data: "get_role_display" },
|
||||||
{data: "groups_display" }, {data: "is_valid" }, {data: "id" }],
|
{data: "groups_display" }, {data: "is_valid" }, {data: "id" }],
|
||||||
op_html: $('#actions').html()
|
op_html: $('#actions').html()
|
||||||
};
|
};
|
||||||
var table = jumpserver.initDataTable(options);
|
table = jumpserver.initDataTable(options);
|
||||||
|
return table
|
||||||
}
|
}
|
||||||
|
|
||||||
$(document).ready(function(){
|
$(document).ready(function(){
|
||||||
renderTable();
|
var table = initTable();
|
||||||
var fields = $('#fm_user_bulk_update .form-group');
|
var fields = $('#fm_user_bulk_update .form-group');
|
||||||
$.each(fields, function (index, value) {
|
$.each(fields, function (index, value) {
|
||||||
console.log(value)
|
console.log(value)
|
||||||
|
@ -158,7 +148,7 @@ $(document).ready(function(){
|
||||||
var id_list = [];
|
var id_list = [];
|
||||||
var plain_id_list = [];
|
var plain_id_list = [];
|
||||||
$data_table.rows({selected: true}).every(function(){
|
$data_table.rows({selected: true}).every(function(){
|
||||||
id_list.push({id: this.data().id});
|
id_list.push({pk: this.data().id});
|
||||||
plain_id_list.push(this.data().id);
|
plain_id_list.push(this.data().id);
|
||||||
});
|
});
|
||||||
if (id_list === []) {
|
if (id_list === []) {
|
||||||
|
@ -169,6 +159,7 @@ $(document).ready(function(){
|
||||||
var body = $.each(id_list, function(index, user_object) {
|
var body = $.each(id_list, function(index, user_object) {
|
||||||
user_object['is_active'] = false;
|
user_object['is_active'] = false;
|
||||||
});
|
});
|
||||||
|
console.log(body);
|
||||||
APIUpdateAttr({url: the_url, method: 'PATCH', body: JSON.stringify(body)});
|
APIUpdateAttr({url: the_url, method: 'PATCH', body: JSON.stringify(body)});
|
||||||
$data_table.ajax.reload();
|
$data_table.ajax.reload();
|
||||||
jumpserver.checked = false;
|
jumpserver.checked = false;
|
||||||
|
|
|
@ -1,12 +1,8 @@
|
||||||
{% extends 'users/_user.html' %}
|
{% extends 'users/_user.html' %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
{% load bootstrap3 %}
|
||||||
{% block user_template_title %}{% trans "Update user" %}{% endblock %}
|
{% block user_template_title %}{% trans "Update user" %}{% endblock %}
|
||||||
{% block password %}
|
{% block password %}
|
||||||
<h3>{% trans 'Password' %}</h3>
|
<h3>{% trans 'Auth' %}</h3>
|
||||||
<div class="form-group">
|
{% bootstrap_field form.password layout="horizontal" %}
|
||||||
<label for="password" class="col-sm-2 control-label">{% trans 'Password' %}</label>
|
|
||||||
<div class="col-sm-9 controls" >
|
|
||||||
<input id="password" name="password" type="password" class="form-control">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -30,8 +30,6 @@ urlpatterns = [
|
||||||
url(r'^user/(?P<pk>[0-9a-zA-Z\-]{36})/update$', views.UserUpdateView.as_view(), name='user-update'),
|
url(r'^user/(?P<pk>[0-9a-zA-Z\-]{36})/update$', views.UserUpdateView.as_view(), name='user-update'),
|
||||||
url(r'^user/update$', views.UserBulkUpdateView.as_view(), name='user-bulk-update'),
|
url(r'^user/update$', views.UserBulkUpdateView.as_view(), name='user-bulk-update'),
|
||||||
url(r'^user/(?P<pk>[0-9a-zA-Z\-]{36})$', views.UserDetailView.as_view(), name='user-detail'),
|
url(r'^user/(?P<pk>[0-9a-zA-Z\-]{36})$', views.UserDetailView.as_view(), name='user-detail'),
|
||||||
url(r'^user/(?P<pk>[0-9a-zA-Z\-]{36})/asset-permission$', views.UserAssetPermissionView.as_view(), name='user-asset-permission'),
|
|
||||||
url(r'^user/(?P<pk>[0-9a-zA-Z\-]{36})/asset-permission/create$', views.UserAssetPermissionCreateView.as_view(), name='user-asset-permission-create'),
|
|
||||||
url(r'^user/(?P<pk>[0-9a-zA-Z\-]{36})/assets', views.UserGrantedAssetView.as_view(), name='user-granted-asset'),
|
url(r'^user/(?P<pk>[0-9a-zA-Z\-]{36})/assets', views.UserGrantedAssetView.as_view(), name='user-granted-asset'),
|
||||||
url(r'^user/(?P<pk>[0-9a-zA-Z\-]{36})/login-history', views.UserDetailView.as_view(), name='user-login-history'),
|
url(r'^user/(?P<pk>[0-9a-zA-Z\-]{36})/login-history', views.UserDetailView.as_view(), name='user-login-history'),
|
||||||
|
|
||||||
|
@ -41,8 +39,6 @@ urlpatterns = [
|
||||||
url(r'^user-group/(?P<pk>[0-9a-zA-Z\-]{36})$', views.UserGroupDetailView.as_view(), name='user-group-detail'),
|
url(r'^user-group/(?P<pk>[0-9a-zA-Z\-]{36})$', views.UserGroupDetailView.as_view(), name='user-group-detail'),
|
||||||
url(r'^user-group/create$', views.UserGroupCreateView.as_view(), name='user-group-create'),
|
url(r'^user-group/create$', views.UserGroupCreateView.as_view(), name='user-group-create'),
|
||||||
url(r'^user-group/(?P<pk>[0-9a-zA-Z\-]{36})/update$', views.UserGroupUpdateView.as_view(), name='user-group-update'),
|
url(r'^user-group/(?P<pk>[0-9a-zA-Z\-]{36})/update$', views.UserGroupUpdateView.as_view(), name='user-group-update'),
|
||||||
url(r'^user-group/(?P<pk>[0-9a-zA-Z\-]{36})/asset-permission$', views.UserGroupAssetPermissionView.as_view(), name='user-group-asset-permission'),
|
|
||||||
url(r'^user-group/(?P<pk>[0-9a-zA-Z\-]{36})/asset-permission/create$', views.UserGroupAssetPermissionCreateView.as_view(), name='user-group-asset-permission-create'),
|
|
||||||
url(r'^user-group/(?P<pk>[0-9a-zA-Z\-]{36})/assets', views.UserGroupGrantedAssetView.as_view(), name='user-group-granted-asset'),
|
url(r'^user-group/(?P<pk>[0-9a-zA-Z\-]{36})/assets', views.UserGroupGrantedAssetView.as_view(), name='user-group-granted-asset'),
|
||||||
|
|
||||||
# Login log
|
# Login log
|
||||||
|
|
|
@ -18,8 +18,7 @@ from ..utils import AdminUserRequiredMixin
|
||||||
from .. import forms
|
from .. import forms
|
||||||
|
|
||||||
__all__ = ['UserGroupListView', 'UserGroupCreateView', 'UserGroupDetailView',
|
__all__ = ['UserGroupListView', 'UserGroupCreateView', 'UserGroupDetailView',
|
||||||
'UserGroupUpdateView', 'UserGroupAssetPermissionCreateView',
|
'UserGroupUpdateView', 'UserGroupGrantedAssetView']
|
||||||
'UserGroupAssetPermissionView', 'UserGroupGrantedAssetView']
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,9 +26,12 @@ class UserGroupListView(AdminUserRequiredMixin, TemplateView):
|
||||||
template_name = 'users/user_group_list.html'
|
template_name = 'users/user_group_list.html'
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super(UserGroupListView, self).get_context_data(**kwargs)
|
context = {
|
||||||
context.update({'app': _('Users'), 'action': _('User group list')})
|
'app': _('Users'),
|
||||||
return context
|
'action': _('User group list')
|
||||||
|
}
|
||||||
|
kwargs.update(context)
|
||||||
|
return super().get_context_data(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
class UserGroupCreateView(AdminUserRequiredMixin, SuccessMessageMixin, CreateView):
|
class UserGroupCreateView(AdminUserRequiredMixin, SuccessMessageMixin, CreateView):
|
||||||
|
@ -40,24 +42,16 @@ class UserGroupCreateView(AdminUserRequiredMixin, SuccessMessageMixin, CreateVie
|
||||||
success_message = '<a href={url}> {name} </a> was created successfully'
|
success_message = '<a href={url}> {name} </a> was created successfully'
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super(UserGroupCreateView, self).get_context_data(**kwargs)
|
context = {
|
||||||
users = User.objects.all()
|
'app': _('Users'),
|
||||||
context.update({'app': _('Users'), 'action': _('Create user group'),
|
'action': _('Create user group'),
|
||||||
'users': users})
|
}
|
||||||
return context
|
kwargs.update(context)
|
||||||
|
return super().get_context_data(**kwargs)
|
||||||
# 需要添加组下用户, 而user并不是group的多对多,所以需要手动建立关系
|
|
||||||
def form_valid(self, form):
|
|
||||||
user_group = form.save()
|
|
||||||
users_id_list = self.request.POST.getlist('users', [])
|
|
||||||
users = User.objects.filter(id__in=users_id_list)
|
|
||||||
user_group.created_by = self.request.user.username or 'Admin'
|
|
||||||
user_group.users.add(*users)
|
|
||||||
user_group.save()
|
|
||||||
return super(UserGroupCreateView, self).form_valid(form)
|
|
||||||
|
|
||||||
def get_success_message(self, cleaned_data):
|
def get_success_message(self, cleaned_data):
|
||||||
url = reverse_lazy('users:user-group-detail',
|
url = reverse_lazy(
|
||||||
|
'users:user-group-detail',
|
||||||
kwargs={'pk': self.object.id}
|
kwargs={'pk': self.object.id}
|
||||||
)
|
)
|
||||||
return self.success_message.format(
|
return self.success_message.format(
|
||||||
|
@ -72,26 +66,16 @@ class UserGroupUpdateView(AdminUserRequiredMixin, UpdateView):
|
||||||
success_url = reverse_lazy('users:user-group-list')
|
success_url = reverse_lazy('users:user-group-list')
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
# self.object = self.get_object()
|
|
||||||
context = super(UserGroupUpdateView, self).get_context_data(**kwargs)
|
|
||||||
users = User.objects.all()
|
users = User.objects.all()
|
||||||
group_users = [user.id for user in self.object.users.all()]
|
group_users = [user.id for user in self.object.users.all()]
|
||||||
context.update({
|
context = {
|
||||||
'app': _('Users'),
|
'app': _('Users'),
|
||||||
'action': _('Update user group'),
|
'action': _('Update user group'),
|
||||||
'users': users,
|
'users': users,
|
||||||
'group_users': group_users
|
'group_users': group_users
|
||||||
})
|
}
|
||||||
return context
|
kwargs.update(context)
|
||||||
|
return super().get_context_data(**kwargs)
|
||||||
def form_valid(self, form):
|
|
||||||
user_group = form.save()
|
|
||||||
users_id_list = self.request.POST.getlist('users', [])
|
|
||||||
users = User.objects.filter(id__in=users_id_list)
|
|
||||||
user_group.users.clear()
|
|
||||||
user_group.users.add(*users)
|
|
||||||
user_group.save()
|
|
||||||
return super(UserGroupUpdateView, self).form_valid(form)
|
|
||||||
|
|
||||||
|
|
||||||
class UserGroupDetailView(AdminUserRequiredMixin, DetailView):
|
class UserGroupDetailView(AdminUserRequiredMixin, DetailView):
|
||||||
|
@ -107,58 +91,7 @@ class UserGroupDetailView(AdminUserRequiredMixin, DetailView):
|
||||||
'users': users,
|
'users': users,
|
||||||
}
|
}
|
||||||
kwargs.update(context)
|
kwargs.update(context)
|
||||||
return super(UserGroupDetailView, self).get_context_data(**kwargs)
|
return super().get_context_data(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
class UserGroupAssetPermissionView(AdminUserRequiredMixin, FormMixin,
|
|
||||||
SingleObjectMixin, ListView):
|
|
||||||
model = UserGroup
|
|
||||||
template_name = 'users/user_group_asset_permission.html'
|
|
||||||
context_object_name = 'user_group'
|
|
||||||
form_class = forms.UserPrivateAssetPermissionForm
|
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
|
||||||
self.object = self.get_object(queryset=UserGroup.objects.all())
|
|
||||||
return super(UserGroupAssetPermissionView, self)\
|
|
||||||
.get(request, *args, **kwargs)
|
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
|
||||||
context = {
|
|
||||||
'app': 'Users',
|
|
||||||
'action': 'User group asset permissions',
|
|
||||||
}
|
|
||||||
kwargs.update(context)
|
|
||||||
return super(UserGroupAssetPermissionView, self)\
|
|
||||||
.get_context_data(**kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class UserGroupAssetPermissionCreateView(AdminUserRequiredMixin, CreateView):
|
|
||||||
form_class = forms.UserGroupPrivateAssetPermissionForm
|
|
||||||
model = AssetPermission
|
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
|
||||||
user_group = self.get_object(queryset=UserGroup.objects.all())
|
|
||||||
return redirect(reverse('users:user-group-asset-permission',
|
|
||||||
kwargs={'pk': user_group.id}))
|
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
|
||||||
self.user_group = self.get_object(queryset=UserGroup.objects.all())
|
|
||||||
return super(UserGroupAssetPermissionCreateView, self)\
|
|
||||||
.post(request, *args, **kwargs)
|
|
||||||
|
|
||||||
def get_form(self, form_class=None):
|
|
||||||
form = super(UserGroupAssetPermissionCreateView, self)\
|
|
||||||
.get_form(form_class=form_class)
|
|
||||||
form.user_group = self.user_group
|
|
||||||
return form
|
|
||||||
|
|
||||||
def form_invalid(self, form):
|
|
||||||
return redirect(reverse('users:user-group-asset-permission',
|
|
||||||
kwargs={'pk': self.user_group.id}))
|
|
||||||
|
|
||||||
def get_success_url(self):
|
|
||||||
return reverse('users:user-group-asset-permission',
|
|
||||||
kwargs={'pk': self.user_group.id})
|
|
||||||
|
|
||||||
|
|
||||||
class UserGroupGrantedAssetView(AdminUserRequiredMixin, DetailView):
|
class UserGroupGrantedAssetView(AdminUserRequiredMixin, DetailView):
|
||||||
|
@ -167,7 +100,8 @@ class UserGroupGrantedAssetView(AdminUserRequiredMixin, DetailView):
|
||||||
context_object_name = 'user_group'
|
context_object_name = 'user_group'
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
self.object = self.get_object(queryset=UserGroup.objects.all())
|
print(kwargs.get('pk'))
|
||||||
|
self.object = self.get_object(queryset=self.model.objects.all())
|
||||||
return super().get(request, *args, **kwargs)
|
return super().get(request, *args, **kwargs)
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
|
@ -176,4 +110,4 @@ class UserGroupGrantedAssetView(AdminUserRequiredMixin, DetailView):
|
||||||
'action': 'User group granted asset',
|
'action': 'User group granted asset',
|
||||||
}
|
}
|
||||||
kwargs.update(context)
|
kwargs.update(context)
|
||||||
return super(UserGroupGrantedAssetView, self).get_context_data(**kwargs)
|
return super().get_context_data(**kwargs)
|
||||||
|
|
|
@ -8,6 +8,7 @@ import csv
|
||||||
import codecs
|
import codecs
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
|
|
||||||
|
from django.contrib import messages
|
||||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
from django.contrib.messages.views import SuccessMessageMixin
|
from django.contrib.messages.views import SuccessMessageMixin
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
|
@ -29,16 +30,15 @@ from django.contrib.auth import logout as auth_logout
|
||||||
|
|
||||||
from .. import forms
|
from .. import forms
|
||||||
from ..models import User, UserGroup
|
from ..models import User, UserGroup
|
||||||
from ..utils import AdminUserRequiredMixin, send_user_created_mail
|
from ..utils import AdminUserRequiredMixin
|
||||||
from ..signals import on_user_created
|
from ..signals import on_user_created
|
||||||
from common.mixins import JSONResponseMixin
|
from common.mixins import JSONResponseMixin
|
||||||
from common.utils import get_logger, get_object_or_none
|
from common.utils import get_logger, get_object_or_none
|
||||||
from perms.models import AssetPermission
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'UserListView', 'UserCreateView', 'UserDetailView',
|
'UserListView', 'UserCreateView', 'UserDetailView',
|
||||||
'UserUpdateView', 'UserAssetPermissionCreateView',
|
'UserUpdateView',
|
||||||
'UserAssetPermissionView', 'UserGrantedAssetView',
|
'UserGrantedAssetView',
|
||||||
'UserExportView', 'UserBulkImportView', 'UserProfileView',
|
'UserExportView', 'UserBulkImportView', 'UserProfileView',
|
||||||
'UserProfileUpdateView', 'UserPasswordUpdateView',
|
'UserProfileUpdateView', 'UserPasswordUpdateView',
|
||||||
'UserPublicKeyUpdateView', 'UserBulkUpdateView',
|
'UserPublicKeyUpdateView', 'UserBulkUpdateView',
|
||||||
|
@ -51,7 +51,7 @@ class UserListView(AdminUserRequiredMixin, TemplateView):
|
||||||
template_name = 'users/user_list.html'
|
template_name = 'users/user_list.html'
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super(UserListView, self).get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
context.update({
|
context.update({
|
||||||
'app': _('Users'),
|
'app': _('Users'),
|
||||||
'action': _('User list'),
|
'action': _('User list'),
|
||||||
|
@ -67,7 +67,7 @@ class UserCreateView(AdminUserRequiredMixin, SuccessMessageMixin, CreateView):
|
||||||
success_message = _('Create user <a href="{url}">{name}</a> successfully.')
|
success_message = _('Create user <a href="{url}">{name}</a> successfully.')
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super(UserCreateView, self).get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
context.update({'app': _('Users'), 'action': _('Create user')})
|
context.update({'app': _('Users'), 'action': _('Create user')})
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ class UserCreateView(AdminUserRequiredMixin, SuccessMessageMixin, CreateView):
|
||||||
user.created_by = self.request.user.username or 'System'
|
user.created_by = self.request.user.username or 'System'
|
||||||
user.save()
|
user.save()
|
||||||
on_user_created.send(self.__class__, user=user)
|
on_user_created.send(self.__class__, user=user)
|
||||||
return super(UserCreateView, self).form_valid(form)
|
return super().form_valid(form)
|
||||||
|
|
||||||
def get_success_message(self, cleaned_data):
|
def get_success_message(self, cleaned_data):
|
||||||
url = reverse_lazy('users:user-detail', kwargs={'pk': self.object.pk})
|
url = reverse_lazy('users:user-detail', kwargs={'pk': self.object.pk})
|
||||||
|
@ -92,31 +92,34 @@ class UserUpdateView(AdminUserRequiredMixin, UpdateView):
|
||||||
context_object_name = 'user_object'
|
context_object_name = 'user_object'
|
||||||
success_url = reverse_lazy('users:user-list')
|
success_url = reverse_lazy('users:user-list')
|
||||||
|
|
||||||
def form_valid(self, form):
|
# def form_valid(self, form):
|
||||||
username = self.object.username
|
# username = self.object.username
|
||||||
user = form.save(commit=False)
|
# user = form.save(commit=False)
|
||||||
user.username = username
|
# user.username = username
|
||||||
user.save()
|
# user.save()
|
||||||
password = self.request.POST.get('password', '')
|
# password = self.request.POST.get('password', '')
|
||||||
if password:
|
# if password:
|
||||||
user.set_password(password)
|
# user.set_password(password)
|
||||||
return super(UserUpdateView, self).form_valid(form)
|
# return super().form_valid(form)
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super(UserUpdateView, self).get_context_data(**kwargs)
|
context = {'app': _('Users'), 'action': _('Update user')}
|
||||||
context.update({'app': _('Users'), 'action': _('Update user')})
|
kwargs.update(context)
|
||||||
return context
|
return super().get_context_data(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
class UserBulkUpdateView(AdminUserRequiredMixin, ListView):
|
class UserBulkUpdateView(AdminUserRequiredMixin, TemplateView):
|
||||||
model = User
|
model = User
|
||||||
form_class = forms.UserBulkUpdateForm
|
form_class = forms.UserBulkUpdateForm
|
||||||
template_name = 'users/user_bulk_update.html'
|
template_name = 'users/user_bulk_update.html'
|
||||||
success_url = reverse_lazy('users:user-list')
|
success_url = reverse_lazy('users:user-list')
|
||||||
|
success_message = _("Bulk update user success")
|
||||||
|
form = None
|
||||||
|
id_list = None
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
users_id = self.request.GET.get('users_id', '')
|
users_id = self.request.GET.get('users_id', '')
|
||||||
self.id_list = [int(i) for i in users_id.split(',') if i.isdigit()]
|
self.id_list = [i for i in users_id.split(',')]
|
||||||
|
|
||||||
if kwargs.get('form'):
|
if kwargs.get('form'):
|
||||||
self.form = kwargs['form']
|
self.form = kwargs['form']
|
||||||
|
@ -126,12 +129,13 @@ class UserBulkUpdateView(AdminUserRequiredMixin, ListView):
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
self.form = self.form_class()
|
self.form = self.form_class()
|
||||||
return super(UserBulkUpdateView, self).get(request, *args, **kwargs)
|
return super().get(request, *args, **kwargs)
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
form = self.form_class(request.POST)
|
form = self.form_class(request.POST)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
form.save()
|
form.save()
|
||||||
|
messages.success(request, self.success_message)
|
||||||
return redirect(self.success_url)
|
return redirect(self.success_url)
|
||||||
else:
|
else:
|
||||||
return self.get(request, form=form, *args, **kwargs)
|
return self.get(request, form=form, *args, **kwargs)
|
||||||
|
@ -145,7 +149,7 @@ class UserBulkUpdateView(AdminUserRequiredMixin, ListView):
|
||||||
'users': User.objects.all(),
|
'users': User.objects.all(),
|
||||||
}
|
}
|
||||||
kwargs.update(context)
|
kwargs.update(context)
|
||||||
return super(UserBulkUpdateView, self).get_context_data(**kwargs)
|
return super().get_context_data(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
class UserDetailView(AdminUserRequiredMixin, DetailView):
|
class UserDetailView(AdminUserRequiredMixin, DetailView):
|
||||||
|
@ -161,19 +165,7 @@ class UserDetailView(AdminUserRequiredMixin, DetailView):
|
||||||
'groups': groups
|
'groups': groups
|
||||||
}
|
}
|
||||||
kwargs.update(context)
|
kwargs.update(context)
|
||||||
return super(UserDetailView, self).get_context_data(**kwargs)
|
return super().get_context_data(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
# USER_ATTR_MAPPING = (
|
|
||||||
# ('name', 'Name'),
|
|
||||||
# ('username', 'Username'),
|
|
||||||
# ('email', 'Email'),
|
|
||||||
# ('groups', 'User groups'),
|
|
||||||
# ('role', 'Role'),
|
|
||||||
# ('phone', 'Phone'),
|
|
||||||
# ('wechat', 'Wechat'),
|
|
||||||
# ('comment', 'Comment'),
|
|
||||||
# )
|
|
||||||
|
|
||||||
|
|
||||||
@method_decorator(csrf_exempt, name='dispatch')
|
@method_decorator(csrf_exempt, name='dispatch')
|
||||||
|
@ -182,14 +174,15 @@ class UserExportView(View):
|
||||||
fields = [
|
fields = [
|
||||||
User._meta.get_field(name)
|
User._meta.get_field(name)
|
||||||
for name in [
|
for name in [
|
||||||
'id', 'name', 'username', 'email', 'role', 'wechat', 'phone',
|
'id', 'name', 'username', 'email', 'role',
|
||||||
'enable_otp', 'is_active', 'comment',
|
'wechat', 'phone', 'is_active', 'comment',
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
spm = request.GET.get('spm', '')
|
spm = request.GET.get('spm', '')
|
||||||
users_id = cache.get(spm, ['1'])
|
users_id = cache.get(spm, [])
|
||||||
filename = 'users-{}.csv'.format(
|
filename = 'users-{}.csv'.format(
|
||||||
timezone.localtime(timezone.now()).strftime('%Y-%m-%d_%H-%M-%S'))
|
timezone.localtime(timezone.now()).strftime('%Y-%m-%d_%H-%M-%S')
|
||||||
|
)
|
||||||
response = HttpResponse(content_type='text/csv')
|
response = HttpResponse(content_type='text/csv')
|
||||||
response['Content-Disposition'] = 'attachment; filename="%s"' % filename
|
response['Content-Disposition'] = 'attachment; filename="%s"' % filename
|
||||||
response.write(codecs.BOM_UTF8)
|
response.write(codecs.BOM_UTF8)
|
||||||
|
@ -233,6 +226,7 @@ class UserBulkImportView(AdminUserRequiredMixin, JSONResponseMixin, FormView):
|
||||||
}
|
}
|
||||||
return self.render_json_response(data)
|
return self.render_json_response(data)
|
||||||
|
|
||||||
|
# todo: need be patch, method to long
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
file = form.cleaned_data['file']
|
file = form.cleaned_data['file']
|
||||||
data = file.read().decode('utf-8').strip(codecs.BOM_UTF8.decode('utf-8'))
|
data = file.read().decode('utf-8').strip(codecs.BOM_UTF8.decode('utf-8'))
|
||||||
|
@ -243,8 +237,8 @@ class UserBulkImportView(AdminUserRequiredMixin, JSONResponseMixin, FormView):
|
||||||
fields = [
|
fields = [
|
||||||
User._meta.get_field(name)
|
User._meta.get_field(name)
|
||||||
for name in [
|
for name in [
|
||||||
'id', 'name', 'username', 'email', 'role', 'wechat', 'phone',
|
'id', 'name', 'username', 'email', 'role',
|
||||||
'enable_otp', 'is_active', 'comment',
|
'wechat', 'phone', 'is_active', 'comment',
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
mapping_reverse = {field.verbose_name: field.name for field in fields}
|
mapping_reverse = {field.verbose_name: field.name for field in fields}
|
||||||
|
@ -261,10 +255,11 @@ class UserBulkImportView(AdminUserRequiredMixin, JSONResponseMixin, FormView):
|
||||||
if set(row) == {''}:
|
if set(row) == {''}:
|
||||||
continue
|
continue
|
||||||
user_dict = dict(zip(attr, row))
|
user_dict = dict(zip(attr, row))
|
||||||
|
print(user_dict)
|
||||||
id_ = user_dict.pop('id', 0)
|
id_ = user_dict.pop('id', 0)
|
||||||
user = get_object_or_none(User, id=id_)
|
user = get_object_or_none(User, id=id_)
|
||||||
for k, v in user_dict.items():
|
for k, v in user_dict.items():
|
||||||
if k in ['enable_otp', 'is_active']:
|
if k in ['is_active']:
|
||||||
if v.lower() == 'false':
|
if v.lower() == 'false':
|
||||||
v = False
|
v = False
|
||||||
else:
|
else:
|
||||||
|
@ -312,63 +307,14 @@ class UserBulkImportView(AdminUserRequiredMixin, JSONResponseMixin, FormView):
|
||||||
return self.render_json_response(data)
|
return self.render_json_response(data)
|
||||||
|
|
||||||
|
|
||||||
class UserAssetPermissionView(AdminUserRequiredMixin, FormMixin,
|
|
||||||
SingleObjectMixin, ListView):
|
|
||||||
model = User
|
|
||||||
template_name = 'users/user_asset_permission.html'
|
|
||||||
context_object_name = 'user'
|
|
||||||
form_class = forms.UserPrivateAssetPermissionForm
|
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
|
||||||
self.object = self.get_object(queryset=User.objects.all())
|
|
||||||
return super(UserAssetPermissionView, self).get(request, *args, **kwargs)
|
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
|
||||||
context = {
|
|
||||||
'app': 'Users',
|
|
||||||
'action': 'User asset permissions',
|
|
||||||
}
|
|
||||||
kwargs.update(context)
|
|
||||||
return super(UserAssetPermissionView, self).get_context_data(**kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class UserAssetPermissionCreateView(AdminUserRequiredMixin, CreateView):
|
|
||||||
form_class = forms.UserPrivateAssetPermissionForm
|
|
||||||
model = AssetPermission
|
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
|
||||||
user = self.get_object(queryset=User.objects.all())
|
|
||||||
return redirect(reverse('users:user-asset-permission',
|
|
||||||
kwargs={'pk': user.id}))
|
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
|
||||||
self.user = self.get_object(queryset=User.objects.all())
|
|
||||||
return super(UserAssetPermissionCreateView, self)\
|
|
||||||
.post(request, *args, **kwargs)
|
|
||||||
|
|
||||||
def get_form(self, form_class=None):
|
|
||||||
form = super(UserAssetPermissionCreateView, self)\
|
|
||||||
.get_form(form_class=form_class)
|
|
||||||
form.user = self.user
|
|
||||||
return form
|
|
||||||
|
|
||||||
def form_invalid(self, form):
|
|
||||||
return redirect(reverse('users:user-asset-permission',
|
|
||||||
kwargs={'pk': self.user.id}))
|
|
||||||
|
|
||||||
def get_success_url(self):
|
|
||||||
return reverse('users:user-asset-permission',
|
|
||||||
kwargs={'pk': self.user.id})
|
|
||||||
|
|
||||||
|
|
||||||
class UserGrantedAssetView(AdminUserRequiredMixin, DetailView):
|
class UserGrantedAssetView(AdminUserRequiredMixin, DetailView):
|
||||||
model = User
|
model = User
|
||||||
template_name = 'users/user_granted_asset.html'
|
template_name = 'users/user_granted_asset.html'
|
||||||
context_object_name = 'user'
|
object = None
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
self.object = self.get_object(queryset=User.objects.all())
|
self.object = self.get_object(queryset=User.objects.all())
|
||||||
return super(UserGrantedAssetView, self).get(request, *args, **kwargs)
|
return super().get(request, *args, **kwargs)
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = {
|
context = {
|
||||||
|
@ -376,7 +322,7 @@ class UserGrantedAssetView(AdminUserRequiredMixin, DetailView):
|
||||||
'action': 'User granted asset',
|
'action': 'User granted asset',
|
||||||
}
|
}
|
||||||
kwargs.update(context)
|
kwargs.update(context)
|
||||||
return super(UserGrantedAssetView, self).get_context_data(**kwargs)
|
return super().get_context_data(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
class UserProfileView(LoginRequiredMixin, TemplateView):
|
class UserProfileView(LoginRequiredMixin, TemplateView):
|
||||||
|
@ -391,7 +337,7 @@ class UserProfileView(LoginRequiredMixin, TemplateView):
|
||||||
'assets': assets,
|
'assets': assets,
|
||||||
}
|
}
|
||||||
kwargs.update(context)
|
kwargs.update(context)
|
||||||
return super(UserProfileView, self).get_context_data(**kwargs)
|
return super().get_context_data(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
class UserProfileUpdateView(LoginRequiredMixin, UpdateView):
|
class UserProfileUpdateView(LoginRequiredMixin, UpdateView):
|
||||||
|
@ -416,7 +362,7 @@ class UserProfileUpdateView(LoginRequiredMixin, UpdateView):
|
||||||
'action': 'Profile update',
|
'action': 'Profile update',
|
||||||
}
|
}
|
||||||
kwargs.update(context)
|
kwargs.update(context)
|
||||||
return super(UserProfileUpdateView, self).get_context_data(**kwargs)
|
return super().get_context_data(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
class UserPasswordUpdateView(LoginRequiredMixin, UpdateView):
|
class UserPasswordUpdateView(LoginRequiredMixin, UpdateView):
|
||||||
|
@ -434,11 +380,11 @@ class UserPasswordUpdateView(LoginRequiredMixin, UpdateView):
|
||||||
'action': 'Password update',
|
'action': 'Password update',
|
||||||
}
|
}
|
||||||
kwargs.update(context)
|
kwargs.update(context)
|
||||||
return super(UserPasswordUpdateView, self).get_context_data(**kwargs)
|
return super().get_context_data(**kwargs)
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self):
|
||||||
auth_logout(self.request)
|
auth_logout(self.request)
|
||||||
return super(UserPasswordUpdateView, self).get_success_url()
|
return super().get_success_url()
|
||||||
|
|
||||||
|
|
||||||
class UserPublicKeyUpdateView(LoginRequiredMixin, UpdateView):
|
class UserPublicKeyUpdateView(LoginRequiredMixin, UpdateView):
|
||||||
|
@ -456,4 +402,4 @@ class UserPublicKeyUpdateView(LoginRequiredMixin, UpdateView):
|
||||||
'action': 'Public key update',
|
'action': 'Public key update',
|
||||||
}
|
}
|
||||||
kwargs.update(context)
|
kwargs.update(context)
|
||||||
return super(UserPublicKeyUpdateView, self).get_context_data(**kwargs)
|
return super().get_context_data(**kwargs)
|
||||||
|
|
Loading…
Reference in New Issue