提交 a308000d 编写于 作者: baltery's avatar baltery

[Bugfix] 修改users模块一些bug

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