mirror of https://github.com/jumpserver/jumpserver
[Update] 控制组织管理员不允许更新、删除超级用户;修复ViewSet API批量更新的bug (#2629)
* [Update] 控制组织管理员不允许编辑(更新、删除)超级用户 - 待续(控制批量更新API) * [Update] 修改方法名称 * [Update] 控制组织管理员不允许批量更新包含超级用户的用户列表 * [Bugfix] 修复所有ViewSet API进行批量更新时rest_framework_bulk库内部的bug * [Update] 修改 OpenID Middleware 日志输出模式 info => debugpull/2632/head^2
parent
aabcf7f31c
commit
caa5060ecd
|
@ -3,6 +3,8 @@
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from common.serializers import AdaptedBulkListSerializer
|
||||||
|
|
||||||
from ..models import Node, AdminUser
|
from ..models import Node, AdminUser
|
||||||
from ..const import ADMIN_USER_CONN_CACHE_KEY
|
from ..const import ADMIN_USER_CONN_CACHE_KEY
|
||||||
|
|
||||||
|
@ -18,6 +20,7 @@ class AdminUserSerializer(serializers.ModelSerializer):
|
||||||
reachable_amount = serializers.SerializerMethodField()
|
reachable_amount = serializers.SerializerMethodField()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
list_serializer_class = AdaptedBulkListSerializer
|
||||||
model = AdminUser
|
model = AdminUser
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from rest_framework_bulk.serializers import BulkListSerializer
|
|
||||||
|
|
||||||
from common.mixins import BulkSerializerMixin
|
from common.mixins import BulkSerializerMixin
|
||||||
|
from common.serializers import AdaptedBulkListSerializer
|
||||||
from ..models import Asset
|
from ..models import Asset
|
||||||
from .system_user import AssetSystemUserSerializer
|
from .system_user import AssetSystemUserSerializer
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ class AssetSerializer(BulkSerializerMixin, serializers.ModelSerializer):
|
||||||
"""
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Asset
|
model = Asset
|
||||||
list_serializer_class = BulkListSerializer
|
list_serializer_class = AdaptedBulkListSerializer
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
validators = []
|
validators = []
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from common.fields import ChoiceDisplayField
|
from common.fields import ChoiceDisplayField
|
||||||
|
from common.serializers import AdaptedBulkListSerializer
|
||||||
from ..models import CommandFilter, CommandFilterRule, SystemUser
|
from ..models import CommandFilter, CommandFilterRule, SystemUser
|
||||||
|
|
||||||
|
|
||||||
|
@ -12,6 +13,7 @@ class CommandFilterSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = CommandFilter
|
model = CommandFilter
|
||||||
|
list_serializer_class = AdaptedBulkListSerializer
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,3 +23,4 @@ class CommandFilterRuleSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = CommandFilterRule
|
model = CommandFilterRule
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
list_serializer_class = AdaptedBulkListSerializer
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
#
|
#
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from common.serializers import AdaptedBulkListSerializer
|
||||||
|
|
||||||
from ..models import Domain, Gateway
|
from ..models import Domain, Gateway
|
||||||
|
|
||||||
|
|
||||||
|
@ -12,6 +14,7 @@ class DomainSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Domain
|
model = Domain
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
list_serializer_class = AdaptedBulkListSerializer
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_asset_count(obj):
|
def get_asset_count(obj):
|
||||||
|
@ -25,6 +28,7 @@ class DomainSerializer(serializers.ModelSerializer):
|
||||||
class GatewaySerializer(serializers.ModelSerializer):
|
class GatewaySerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Gateway
|
model = Gateway
|
||||||
|
list_serializer_class = AdaptedBulkListSerializer
|
||||||
fields = [
|
fields = [
|
||||||
'id', 'name', 'ip', 'port', 'protocol', 'username',
|
'id', 'name', 'ip', 'port', 'protocol', 'username',
|
||||||
'domain', 'is_active', 'date_created', 'date_updated',
|
'domain', 'is_active', 'date_created', 'date_updated',
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from rest_framework_bulk.serializers import BulkListSerializer
|
|
||||||
|
from common.serializers import AdaptedBulkListSerializer
|
||||||
|
|
||||||
from ..models import Label
|
from ..models import Label
|
||||||
|
|
||||||
|
@ -12,7 +13,7 @@ class LabelSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Label
|
model = Label
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
list_serializer_class = BulkListSerializer
|
list_serializer_class = AdaptedBulkListSerializer
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_asset_count(obj):
|
def get_asset_count(obj):
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from common.serializers import AdaptedBulkListSerializer
|
||||||
|
|
||||||
from ..models import SystemUser, Asset
|
from ..models import SystemUser, Asset
|
||||||
from .base import AuthSerializer
|
from .base import AuthSerializer
|
||||||
|
|
||||||
|
@ -17,6 +19,7 @@ class SystemUserSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = SystemUser
|
model = SystemUser
|
||||||
exclude = ('_password', '_private_key', '_public_key')
|
exclude = ('_password', '_private_key', '_public_key')
|
||||||
|
list_serializer_class = AdaptedBulkListSerializer
|
||||||
|
|
||||||
def get_field_names(self, declared_fields, info):
|
def get_field_names(self, declared_fields, info):
|
||||||
fields = super(SystemUserSerializer, self).get_field_names(declared_fields, info)
|
fields = super(SystemUserSerializer, self).get_field_names(declared_fields, info)
|
||||||
|
|
|
@ -23,15 +23,15 @@ class OpenIDAuthenticationMiddleware(MiddlewareMixin):
|
||||||
def process_request(self, request):
|
def process_request(self, request):
|
||||||
# Don't need openid auth if AUTH_OPENID is False
|
# Don't need openid auth if AUTH_OPENID is False
|
||||||
if not settings.AUTH_OPENID:
|
if not settings.AUTH_OPENID:
|
||||||
logger.info("Not settings.AUTH_OPENID")
|
logger.debug("Not settings.AUTH_OPENID")
|
||||||
return
|
return
|
||||||
# Don't need check single logout if user not authenticated
|
# Don't need check single logout if user not authenticated
|
||||||
if not request.user.is_authenticated:
|
if not request.user.is_authenticated:
|
||||||
logger.info("User is not authenticated")
|
logger.debug("User is not authenticated")
|
||||||
return
|
return
|
||||||
elif not request.session[BACKEND_SESSION_KEY].endswith(
|
elif not request.session[BACKEND_SESSION_KEY].endswith(
|
||||||
BACKEND_OPENID_AUTH_CODE):
|
BACKEND_OPENID_AUTH_CODE):
|
||||||
logger.info("BACKEND_SESSION_KEY is not BACKEND_OPENID_AUTH_CODE")
|
logger.debug("BACKEND_SESSION_KEY is not BACKEND_OPENID_AUTH_CODE")
|
||||||
return
|
return
|
||||||
|
|
||||||
# Check openid user single logout or not with access_token
|
# Check openid user single logout or not with access_token
|
||||||
|
@ -40,7 +40,6 @@ class OpenIDAuthenticationMiddleware(MiddlewareMixin):
|
||||||
client.openid_connect_client.userinfo(
|
client.openid_connect_client.userinfo(
|
||||||
token=request.session.get(OIDT_ACCESS_TOKEN)
|
token=request.session.get(OIDT_ACCESS_TOKEN)
|
||||||
)
|
)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logout(request)
|
logout(request)
|
||||||
logger.error(e)
|
logger.error(e)
|
||||||
|
|
|
@ -4,6 +4,10 @@ from django.db import models
|
||||||
from django.http import JsonResponse
|
from django.http import JsonResponse
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
from rest_framework.utils import html
|
||||||
|
from rest_framework.settings import api_settings
|
||||||
|
from rest_framework.exceptions import ValidationError
|
||||||
|
from rest_framework.fields import SkipField
|
||||||
|
|
||||||
|
|
||||||
class NoDeleteQuerySet(models.query.QuerySet):
|
class NoDeleteQuerySet(models.query.QuerySet):
|
||||||
|
@ -89,6 +93,60 @@ class BulkSerializerMixin(object):
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
class BulkListSerializerMixin(object):
|
||||||
|
"""
|
||||||
|
Become rest_framework_bulk doing bulk update raise Exception:
|
||||||
|
'QuerySet' object has no attribute 'pk' when doing bulk update
|
||||||
|
so rewrite it .
|
||||||
|
https://github.com/miki725/django-rest-framework-bulk/issues/68
|
||||||
|
"""
|
||||||
|
|
||||||
|
def to_internal_value(self, data):
|
||||||
|
"""
|
||||||
|
List of dicts of native values <- List of dicts of primitive datatypes.
|
||||||
|
"""
|
||||||
|
if html.is_html_input(data):
|
||||||
|
data = html.parse_html_list(data)
|
||||||
|
|
||||||
|
if not isinstance(data, list):
|
||||||
|
message = self.error_messages['not_a_list'].format(
|
||||||
|
input_type=type(data).__name__
|
||||||
|
)
|
||||||
|
raise ValidationError({
|
||||||
|
api_settings.NON_FIELD_ERRORS_KEY: [message]
|
||||||
|
}, code='not_a_list')
|
||||||
|
|
||||||
|
if not self.allow_empty and len(data) == 0:
|
||||||
|
if self.parent and self.partial:
|
||||||
|
raise SkipField()
|
||||||
|
|
||||||
|
message = self.error_messages['empty']
|
||||||
|
raise ValidationError({
|
||||||
|
api_settings.NON_FIELD_ERRORS_KEY: [message]
|
||||||
|
}, code='empty')
|
||||||
|
|
||||||
|
ret = []
|
||||||
|
errors = []
|
||||||
|
|
||||||
|
for item in data:
|
||||||
|
try:
|
||||||
|
# prepare child serializer to only handle one instance
|
||||||
|
self.child.instance = self.instance.get(id=item['id']) if self.instance else None
|
||||||
|
self.child.initial_data = item
|
||||||
|
# raw
|
||||||
|
validated = self.child.run_validation(item)
|
||||||
|
except ValidationError as exc:
|
||||||
|
errors.append(exc.detail)
|
||||||
|
else:
|
||||||
|
ret.append(validated)
|
||||||
|
errors.append({})
|
||||||
|
|
||||||
|
if any(errors):
|
||||||
|
raise ValidationError(errors)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
class DatetimeSearchMixin:
|
class DatetimeSearchMixin:
|
||||||
date_format = '%Y-%m-%d'
|
date_format = '%Y-%m-%d'
|
||||||
date_from = date_to = None
|
date_from = date_to = None
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
|
||||||
|
from .mixins import BulkListSerializerMixin
|
||||||
|
from rest_framework_bulk.serializers import BulkListSerializer
|
||||||
|
|
||||||
|
|
||||||
|
class AdaptedBulkListSerializer(BulkListSerializerMixin, BulkListSerializer):
|
||||||
|
pass
|
|
@ -1,11 +1,11 @@
|
||||||
|
|
||||||
from rest_framework.serializers import ModelSerializer
|
from rest_framework.serializers import ModelSerializer
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from rest_framework_bulk import BulkListSerializer
|
|
||||||
|
|
||||||
from users.models import User, UserGroup
|
from users.models import User, UserGroup
|
||||||
from assets.models import Asset, Domain, AdminUser, SystemUser, Label
|
from assets.models import Asset, Domain, AdminUser, SystemUser, Label
|
||||||
from perms.models import AssetPermission
|
from perms.models import AssetPermission
|
||||||
|
from common.serializers import AdaptedBulkListSerializer
|
||||||
from .utils import set_current_org, get_current_org
|
from .utils import set_current_org, get_current_org
|
||||||
from .models import Organization
|
from .models import Organization
|
||||||
from .mixins import OrgMembershipSerializerMixin
|
from .mixins import OrgMembershipSerializerMixin
|
||||||
|
@ -14,7 +14,7 @@ from .mixins import OrgMembershipSerializerMixin
|
||||||
class OrgSerializer(ModelSerializer):
|
class OrgSerializer(ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Organization
|
model = Organization
|
||||||
list_serializer_class = BulkListSerializer
|
list_serializer_class = AdaptedBulkListSerializer
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
read_only_fields = ['created_by', 'date_created']
|
read_only_fields = ['created_by', 'date_created']
|
||||||
|
|
||||||
|
@ -70,12 +70,12 @@ class OrgReadSerializer(ModelSerializer):
|
||||||
class OrgMembershipAdminSerializer(OrgMembershipSerializerMixin, ModelSerializer):
|
class OrgMembershipAdminSerializer(OrgMembershipSerializerMixin, ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Organization.admins.through
|
model = Organization.admins.through
|
||||||
list_serializer_class = BulkListSerializer
|
list_serializer_class = AdaptedBulkListSerializer
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
|
||||||
|
|
||||||
class OrgMembershipUserSerializer(OrgMembershipSerializerMixin, ModelSerializer):
|
class OrgMembershipUserSerializer(OrgMembershipSerializerMixin, ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Organization.users.through
|
model = Organization.users.through
|
||||||
list_serializer_class = BulkListSerializer
|
list_serializer_class = AdaptedBulkListSerializer
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from rest_framework_bulk.serializers import BulkListSerializer
|
|
||||||
|
|
||||||
from common.mixins import BulkSerializerMixin
|
from common.mixins import BulkSerializerMixin
|
||||||
|
from common.serializers import AdaptedBulkListSerializer
|
||||||
from ..models import Terminal, Status, Session, Task
|
from ..models import Terminal, Status, Session, Task
|
||||||
|
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ class SessionSerializer(BulkSerializerMixin, serializers.ModelSerializer):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Session
|
model = Session
|
||||||
list_serializer_class = BulkListSerializer
|
list_serializer_class = AdaptedBulkListSerializer
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ class TaskSerializer(BulkSerializerMixin, serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
model = Task
|
model = Task
|
||||||
list_serializer_class = BulkListSerializer
|
list_serializer_class = AdaptedBulkListSerializer
|
||||||
|
|
||||||
|
|
||||||
class ReplaySerializer(serializers.Serializer):
|
class ReplaySerializer(serializers.Serializer):
|
||||||
|
|
|
@ -5,6 +5,7 @@ from django.core.cache import cache
|
||||||
from django.contrib.auth import logout
|
from django.contrib.auth import logout
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
|
from rest_framework import status
|
||||||
from rest_framework import generics
|
from rest_framework import generics
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.permissions import IsAuthenticated
|
from rest_framework.permissions import IsAuthenticated
|
||||||
|
@ -52,9 +53,72 @@ class UserViewSet(IDInFilterMixin, BulkModelViewSet):
|
||||||
self.permission_classes = (IsOrgAdminOrAppUser,)
|
self.permission_classes = (IsOrgAdminOrAppUser,)
|
||||||
return super().get_permissions()
|
return super().get_permissions()
|
||||||
|
|
||||||
|
def _deny_permission(self, instance):
|
||||||
|
"""
|
||||||
|
check current user has permission to handle instance
|
||||||
|
(update, destroy, bulk_update, bulk destroy)
|
||||||
|
"""
|
||||||
|
return not self.request.user.is_superuser and instance.is_superuser
|
||||||
|
|
||||||
|
def destroy(self, request, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
rewrite because limit org_admin destroy superuser
|
||||||
|
"""
|
||||||
|
instance = self.get_object()
|
||||||
|
if self._deny_permission(instance):
|
||||||
|
data = {'msg': _("You do not have permission.")}
|
||||||
|
return Response(data=data, status=status.HTTP_403_FORBIDDEN)
|
||||||
|
|
||||||
|
return super().destroy(request, *args, **kwargs)
|
||||||
|
|
||||||
|
def update(self, request, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
rewrite because limit org_admin update superuser
|
||||||
|
"""
|
||||||
|
instance = self.get_object()
|
||||||
|
if self._deny_permission(instance):
|
||||||
|
data = {'msg': _("You do not have permission.")}
|
||||||
|
return Response(data=data, status=status.HTTP_403_FORBIDDEN)
|
||||||
|
|
||||||
|
return super().update(request, *args, **kwargs)
|
||||||
|
|
||||||
|
def _bulk_deny_permission(self, instances):
|
||||||
|
deny_instances = [i for i in instances if self._deny_permission(i)]
|
||||||
|
if len(deny_instances) > 0:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
def allow_bulk_destroy(self, qs, filtered):
|
def allow_bulk_destroy(self, qs, filtered):
|
||||||
|
if self._bulk_deny_permission(filtered):
|
||||||
|
return False
|
||||||
return qs.count() != filtered.count()
|
return qs.count() != filtered.count()
|
||||||
|
|
||||||
|
def bulk_update(self, request, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
rewrite because limit org_admin update superuser
|
||||||
|
"""
|
||||||
|
partial = kwargs.pop('partial', False)
|
||||||
|
|
||||||
|
# restrict the update to the filtered queryset
|
||||||
|
queryset = self.filter_queryset(self.get_queryset())
|
||||||
|
if self._bulk_deny_permission(queryset):
|
||||||
|
data = {'msg': _("You do not have permission.")}
|
||||||
|
return Response(data=data, status=status.HTTP_403_FORBIDDEN)
|
||||||
|
|
||||||
|
serializer = self.get_serializer(
|
||||||
|
queryset, data=request.data, many=True, partial=partial,
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
serializer.is_valid(raise_exception=True)
|
||||||
|
except Exception as e:
|
||||||
|
data = {'error': str(e)}
|
||||||
|
return Response(data=data, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
self.perform_bulk_update(serializer)
|
||||||
|
return Response(serializer.data, status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
|
||||||
class UserChangePasswordApi(generics.RetrieveUpdateAPIView):
|
class UserChangePasswordApi(generics.RetrieveUpdateAPIView):
|
||||||
permission_classes = (IsOrgAdmin,)
|
permission_classes = (IsOrgAdmin,)
|
||||||
|
|
|
@ -3,10 +3,10 @@
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from rest_framework_bulk import BulkListSerializer
|
|
||||||
|
|
||||||
from common.utils import get_signer, validate_ssh_public_key
|
from common.utils import get_signer, validate_ssh_public_key
|
||||||
from common.mixins import BulkSerializerMixin
|
from common.mixins import BulkSerializerMixin
|
||||||
|
from common.serializers import AdaptedBulkListSerializer
|
||||||
from ..models import User, UserGroup
|
from ..models import User, UserGroup
|
||||||
|
|
||||||
signer = get_signer()
|
signer = get_signer()
|
||||||
|
@ -16,7 +16,7 @@ class UserSerializer(BulkSerializerMixin, serializers.ModelSerializer):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = User
|
model = User
|
||||||
list_serializer_class = BulkListSerializer
|
list_serializer_class = AdaptedBulkListSerializer
|
||||||
fields = [
|
fields = [
|
||||||
'id', 'name', 'username', 'email', 'groups', 'groups_display',
|
'id', 'name', 'username', 'email', 'groups', 'groups_display',
|
||||||
'role', 'role_display', 'avatar_url', 'wechat', 'phone',
|
'role', 'role_display', 'avatar_url', 'wechat', 'phone',
|
||||||
|
@ -52,7 +52,7 @@ class UserGroupSerializer(BulkSerializerMixin, serializers.ModelSerializer):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = UserGroup
|
model = UserGroup
|
||||||
list_serializer_class = BulkListSerializer
|
list_serializer_class = AdaptedBulkListSerializer
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
read_only_fields = ['created_by']
|
read_only_fields = ['created_by']
|
||||||
|
|
||||||
|
|
|
@ -22,11 +22,11 @@
|
||||||
<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>
|
||||||
<li class="pull-right">
|
<li class="pull-right">
|
||||||
<a class="btn btn-outline btn-default" href="{% url 'users:user-update' pk=user_object.id %}"><i class="fa fa-edit"></i>{% trans 'Update' %}</a>
|
<a class="btn btn-outline {% if user_object.is_superuser and not request.user.is_superuser %} disabled {% else %} btn-default {% endif %}" href="{% url 'users:user-update' pk=user_object.id %}"><i class="fa fa-edit"></i>{% trans 'Update' %}</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="pull-right">
|
<li class="pull-right">
|
||||||
<a class="btn btn-outline {% if request.user != user_object and user_object.username != "admin" %} btn-danger btn-delete-user {% else %} disabled {% endif %}">
|
<a class="btn btn-outline {% if request.user == user_object or user_object.username == "admin" or user_object.is_superuser and not request.user.is_superuser %} disabled {% else %} btn-danger btn-delete-user {% endif %}">
|
||||||
<i class="fa fa-trash-o"></i>{% trans 'Delete' %}
|
<i class="fa fa-trash-o"></i>{% trans 'Delete' %}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -77,10 +77,16 @@ function initTable() {
|
||||||
}
|
}
|
||||||
}},
|
}},
|
||||||
{targets: 7, createdCell: function (td, cellData, rowData) {
|
{targets: 7, createdCell: function (td, cellData, rowData) {
|
||||||
var update_btn = '<a href="{% url "users:user-update" pk=DEFAULT_PK %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'.replace('00000000-0000-0000-0000-000000000000', cellData);
|
var update_btn = "";
|
||||||
|
if (rowData.role === 'Admin' && ('{{ request.user.role }}' !== 'Admin')) {
|
||||||
|
update_btn = '<a class="btn btn-xs disabled btn-info">{% trans "Update" %}</a>';
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
update_btn = '<a href="{% url "users:user-update" pk=DEFAULT_PK %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'.replace('00000000-0000-0000-0000-000000000000', cellData);
|
||||||
|
}
|
||||||
|
|
||||||
var del_btn = "";
|
var del_btn = "";
|
||||||
if (rowData.id === 1 || rowData.username === "admin" || rowData.username === "{{ request.user.username }}") {
|
if (rowData.id === 1 || rowData.username === "admin" || rowData.username === "{{ request.user.username }}" || (rowData.role === 'Admin' && ('{{ request.user.role }}' !== 'Admin'))) {
|
||||||
del_btn = '<a class="btn btn-xs btn-danger m-l-xs" disabled>{% trans "Delete" %}</a>'
|
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);
|
||||||
|
|
|
@ -107,6 +107,15 @@ class UserUpdateView(AdminUserRequiredMixin, SuccessMessageMixin, UpdateView):
|
||||||
success_url = reverse_lazy('users:user-list')
|
success_url = reverse_lazy('users:user-list')
|
||||||
success_message = update_success_msg
|
success_message = update_success_msg
|
||||||
|
|
||||||
|
def _deny_permission(self):
|
||||||
|
obj = self.get_object()
|
||||||
|
return not self.request.user.is_superuser and obj.is_superuser
|
||||||
|
|
||||||
|
def get(self, request, *args, **kwargs):
|
||||||
|
if self._deny_permission():
|
||||||
|
return redirect(self.success_url)
|
||||||
|
return super().get(request, *args, **kwargs)
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
check_rules = get_password_check_rules()
|
check_rules = get_password_check_rules()
|
||||||
context = {
|
context = {
|
||||||
|
|
Loading…
Reference in New Issue