[Bugfix] 修改users模块一些bug

pull/828/merge
ibuler 2017-12-18 18:38:30 +08:00
parent e1163895e2
commit a308000d2e
32 changed files with 400 additions and 922 deletions

View File

@ -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

View File

@ -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()

View File

@ -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')),
] ]

View File

@ -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):

View File

@ -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:

View File

@ -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 = [

View File

@ -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()

View File

@ -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

View File

@ -1,2 +0,0 @@
# ~*~ coding: utf-8 ~*~

View File

@ -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

View File

@ -1,8 +0,0 @@
# ~*~ coding: utf-8 ~*~
from .base import ReplayBase
class ReplayStore(ReplayBase):
pass

View File

@ -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()

View File

@ -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

View File

@ -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,)

View File

@ -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)\

View File

@ -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()
#

View File

@ -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)

View File

@ -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" %}

View File

@ -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 %}

View File

@ -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" >

View File

@ -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 %}';

View File

@ -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);

View File

@ -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 %}

View File

@ -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">

View File

@ -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>

View File

@ -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>

View File

@ -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);

View File

@ -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;

View File

@ -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 %}

View File

@ -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

View File

@ -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)

View File

@ -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)