mirror of https://github.com/jumpserver/jumpserver
Merge branch 'lina' of https://github.com/jumpserver/jumpserver into lina
commit
196f1654ab
|
@ -0,0 +1,7 @@
|
|||
|
||||
GET = 'GET'
|
||||
POST = 'POST'
|
||||
PUT = 'PUT'
|
||||
PATCH = 'PATCH'
|
||||
DELETE = 'DELETE'
|
||||
OPTIONS = 'OPTIONS'
|
|
@ -3,7 +3,9 @@
|
|||
import time
|
||||
from hashlib import md5
|
||||
from threading import Thread
|
||||
from collections import defaultdict
|
||||
|
||||
from django.db.models.signals import m2m_changed
|
||||
from django.core.cache import cache
|
||||
from django.http import JsonResponse
|
||||
from rest_framework.response import Response
|
||||
|
@ -14,7 +16,7 @@ from ..utils import lazyproperty
|
|||
|
||||
__all__ = [
|
||||
"JSONResponseMixin", "CommonApiMixin",
|
||||
'AsyncApiMixin',
|
||||
'AsyncApiMixin', 'RelationMixin'
|
||||
]
|
||||
|
||||
|
||||
|
@ -187,3 +189,47 @@ class AsyncApiMixin(InterceptMixin):
|
|||
data["error"] = str(e)
|
||||
data["status"] = "error"
|
||||
cache.set(key, data, 600)
|
||||
|
||||
|
||||
class RelationMixin:
|
||||
m2m_field = None
|
||||
from_field = None
|
||||
to_field = None
|
||||
to_model = None
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
assert self.m2m_field is not None, '''
|
||||
`m2m_field` should not be `None`
|
||||
'''
|
||||
|
||||
self.from_field = self.m2m_field.m2m_field_name()
|
||||
self.to_field = self.m2m_field.m2m_reverse_field_name()
|
||||
self.to_model = self.m2m_field.related_model
|
||||
self.through = getattr(self.m2m_field.model, self.m2m_field.attname).through
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = self.through.objects.all()
|
||||
return queryset
|
||||
|
||||
def send_post_add_signal(self, instances):
|
||||
if not isinstance(instances, list):
|
||||
instances = [instances]
|
||||
|
||||
from_to_mapper = defaultdict(list)
|
||||
|
||||
for i in instances:
|
||||
to_id = getattr(i, self.to_field).id
|
||||
from_obj = getattr(i, self.from_field)
|
||||
from_to_mapper[from_obj].append(to_id)
|
||||
|
||||
for from_obj, to_ids in from_to_mapper.items():
|
||||
m2m_changed.send(
|
||||
sender=self.through, instance=from_obj, action='post_add',
|
||||
reverse=False, model=self.to_model, pk_set=to_ids
|
||||
)
|
||||
|
||||
def perform_create(self, serializer):
|
||||
instance = serializer.save()
|
||||
self.send_post_add_signal(instance)
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
from django.shortcuts import get_object_or_404
|
||||
from rest_framework.viewsets import ModelViewSet, GenericViewSet
|
||||
from rest_framework_bulk import BulkModelViewSet
|
||||
from common.mixins import CommonApiMixin
|
||||
from common.mixins import CommonApiMixin, RelationMixin
|
||||
from orgs.utils import current_org
|
||||
|
||||
from ..utils import set_to_root_org, filter_org_queryset
|
||||
from ..models import Organization
|
||||
|
@ -80,3 +81,12 @@ class OrgMembershipModelViewSetMixin:
|
|||
def get_queryset(self):
|
||||
queryset = self.membership_class.objects.filter(organization=self.org)
|
||||
return queryset
|
||||
|
||||
|
||||
class OrgRelationMixin(RelationMixin):
|
||||
def get_queryset(self):
|
||||
queryset = super().get_queryset()
|
||||
org_id = current_org.org_id()
|
||||
if org_id is not None:
|
||||
queryset = queryset.filter(**{f'{self.from_field}__org_id': org_id})
|
||||
return queryset
|
||||
|
|
|
@ -6,6 +6,7 @@ from .user_permission import *
|
|||
from .asset_permission_relation import *
|
||||
from .user_group_permission import *
|
||||
from .remote_app_permission import *
|
||||
from .remote_app_permission_relation import *
|
||||
from .user_remote_app_permission import *
|
||||
from .database_app_permission import *
|
||||
from .database_app_permission_relation import *
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
from django.db.models import F
|
||||
from orgs.mixins.api import OrgBulkModelViewSet
|
||||
from orgs.mixins.api import OrgRelationMixin
|
||||
|
||||
|
||||
__all__ = [
|
||||
'RelationViewSet'
|
||||
]
|
||||
|
||||
|
||||
class RelationViewSet(OrgRelationMixin, OrgBulkModelViewSet):
|
||||
def get_queryset(self):
|
||||
queryset = super().get_queryset()
|
||||
queryset = queryset.annotate(**{f'{self.from_field}_display': F(f'{self.from_field}__name')})
|
||||
return queryset
|
|
@ -1,14 +1,12 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
from rest_framework import generics
|
||||
from django.db.models import F, Value
|
||||
from django.db.models.functions import Concat
|
||||
from django.shortcuts import get_object_or_404
|
||||
|
||||
from orgs.mixins.api import OrgBulkModelViewSet
|
||||
from orgs.utils import current_org
|
||||
from common.permissions import IsOrgAdmin
|
||||
from .base import RelationViewSet
|
||||
from .. import models, serializers
|
||||
|
||||
__all__ = [
|
||||
|
@ -21,19 +19,9 @@ __all__ = [
|
|||
]
|
||||
|
||||
|
||||
class RelationMixin(OrgBulkModelViewSet):
|
||||
def get_queryset(self):
|
||||
queryset = self.model.objects.all()
|
||||
org_id = current_org.org_id()
|
||||
if org_id is not None:
|
||||
queryset = queryset.filter(databaseapppermission__org_id=org_id)
|
||||
queryset = queryset.annotate(databaseapppermission_display=F('databaseapppermission__name'))
|
||||
return queryset
|
||||
|
||||
|
||||
class DatabaseAppPermissionUserRelationViewSet(RelationMixin):
|
||||
class DatabaseAppPermissionUserRelationViewSet(RelationViewSet):
|
||||
serializer_class = serializers.DatabaseAppPermissionUserRelationSerializer
|
||||
model = models.DatabaseAppPermission.users.through
|
||||
m2m_field = models.DatabaseAppPermission.users.field
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
filterset_fields = [
|
||||
'id', 'user', 'databaseapppermission'
|
||||
|
@ -46,9 +34,9 @@ class DatabaseAppPermissionUserRelationViewSet(RelationMixin):
|
|||
return queryset
|
||||
|
||||
|
||||
class DatabaseAppPermissionUserGroupRelationViewSet(RelationMixin):
|
||||
class DatabaseAppPermissionUserGroupRelationViewSet(RelationViewSet):
|
||||
serializer_class = serializers.DatabaseAppPermissionUserGroupRelationSerializer
|
||||
model = models.DatabaseAppPermission.user_groups.through
|
||||
m2m_field = models.DatabaseAppPermission.user_groups.field
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
filterset_fields = [
|
||||
'id', "usergroup", "databaseapppermission"
|
||||
|
@ -77,9 +65,9 @@ class DatabaseAppPermissionAllUserListApi(generics.ListAPIView):
|
|||
return users
|
||||
|
||||
|
||||
class DatabaseAppPermissionDatabaseAppRelationViewSet(RelationMixin):
|
||||
class DatabaseAppPermissionDatabaseAppRelationViewSet(RelationViewSet):
|
||||
serializer_class = serializers.DatabaseAppPermissionDatabaseAppRelationSerializer
|
||||
model = models.DatabaseAppPermission.database_apps.through
|
||||
m2m_field = models.DatabaseAppPermission.database_apps.field
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
filterset_fields = [
|
||||
'id', 'databaseapp', 'databaseapppermission',
|
||||
|
@ -110,9 +98,9 @@ class DatabaseAppPermissionAllDatabaseAppListApi(generics.ListAPIView):
|
|||
return database_apps
|
||||
|
||||
|
||||
class DatabaseAppPermissionSystemUserRelationViewSet(RelationMixin):
|
||||
class DatabaseAppPermissionSystemUserRelationViewSet(RelationViewSet):
|
||||
serializer_class = serializers.DatabaseAppPermissionSystemUserRelationSerializer
|
||||
model = models.DatabaseAppPermission.system_users.through
|
||||
m2m_field = models.DatabaseAppPermission.system_users.field
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
filterset_fields = [
|
||||
'id', 'systemuser', 'databaseapppermission'
|
||||
|
|
|
@ -13,7 +13,6 @@ from ..serializers import (
|
|||
RemoteAppPermissionUpdateRemoteAppSerializer,
|
||||
)
|
||||
|
||||
|
||||
__all__ = [
|
||||
'RemoteAppPermissionViewSet',
|
||||
'RemoteAppPermissionAddUserApi', 'RemoteAppPermissionAddRemoteAppApi',
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
from perms.api.base import RelationViewSet
|
||||
from rest_framework import generics
|
||||
from django.db.models import F
|
||||
from django.shortcuts import get_object_or_404
|
||||
|
||||
from common.permissions import IsOrgAdmin
|
||||
from .. import models, serializers
|
||||
|
||||
__all__ = [
|
||||
'RemoteAppPermissionUserRelationViewSet',
|
||||
'RemoteAppPermissionRemoteAppRelationViewSet',
|
||||
'RemoteAppPermissionAllRemoteAppListApi',
|
||||
'RemoteAppPermissionAllUserListApi',
|
||||
]
|
||||
|
||||
|
||||
class RemoteAppPermissionAllUserListApi(generics.ListAPIView):
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
serializer_class = serializers.PermissionAllUserSerializer
|
||||
filter_fields = ("username", "name")
|
||||
search_fields = filter_fields
|
||||
|
||||
def get_queryset(self):
|
||||
pk = self.kwargs.get("pk")
|
||||
perm = get_object_or_404(models.RemoteAppPermission, pk=pk)
|
||||
users = perm.all_users.only(
|
||||
*self.serializer_class.Meta.only_fields
|
||||
)
|
||||
return users
|
||||
|
||||
|
||||
class RemoteAppPermissionUserRelationViewSet(RelationViewSet):
|
||||
serializer_class = serializers.RemoteAppPermissionUserRelationSerializer
|
||||
m2m_field = models.RemoteAppPermission.users.field
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
filterset_fields = [
|
||||
'id', 'user', 'remoteapppermission'
|
||||
]
|
||||
search_fields = ('user__name', 'user__username', 'remoteapppermission__name')
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = super().get_queryset()
|
||||
queryset = queryset.annotate(user_display=F('user__name'))
|
||||
return queryset
|
||||
|
||||
|
||||
class RemoteAppPermissionRemoteAppRelationViewSet(RelationViewSet):
|
||||
serializer_class = serializers.RemoteAppPermissionRemoteAppRelationSerializer
|
||||
m2m_field = models.RemoteAppPermission.remote_apps.field
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
filterset_fields = [
|
||||
'id', 'remoteapp', 'remoteapppermission',
|
||||
]
|
||||
search_fields = [
|
||||
"id", "remoteapp__name", "remoteapppermission__name"
|
||||
]
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = super().get_queryset()
|
||||
queryset = queryset \
|
||||
.annotate(remoteapp_display=F('remoteapp__name'))
|
||||
return queryset
|
||||
|
||||
|
||||
class RemoteAppPermissionAllRemoteAppListApi(generics.ListAPIView):
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
serializer_class = serializers.RemoteAppPermissionAllRemoteAppSerializer
|
||||
filter_fields = ("name",)
|
||||
search_fields = filter_fields
|
||||
|
||||
def get_queryset(self):
|
||||
pk = self.kwargs.get("pk")
|
||||
perm = get_object_or_404(models.RemoteAppPermission, pk=pk)
|
||||
remote_apps = perm.all_remote_apps.only(
|
||||
*self.serializer_class.Meta.only_fields
|
||||
)
|
||||
return remote_apps
|
|
@ -79,6 +79,23 @@ class BasePermission(OrgModelMixin):
|
|||
return True
|
||||
return False
|
||||
|
||||
@property
|
||||
def all_users(self):
|
||||
from users.models import User
|
||||
|
||||
users_query = self._meta.get_field('users').related_query_name()
|
||||
user_groups_query = self._meta.get_field('user_groups').related_query_name()
|
||||
|
||||
users_q = Q(**{
|
||||
f'{users_query}': self
|
||||
})
|
||||
|
||||
user_groups_q = Q(**{
|
||||
f'groups__{user_groups_query}': self
|
||||
})
|
||||
|
||||
return User.objects.filter(users_q | user_groups_q).distinct()
|
||||
|
||||
def get_all_users(self):
|
||||
from users.models import User
|
||||
users_id = self.users.all().values_list('id', flat=True)
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from common.utils import lazyproperty
|
||||
from .base import BasePermission
|
||||
|
||||
__all__ = [
|
||||
|
@ -28,3 +29,11 @@ class DatabaseAppPermission(BasePermission):
|
|||
|
||||
def get_all_database_apps(self):
|
||||
return self.database_apps.all()
|
||||
|
||||
@lazyproperty
|
||||
def database_apps_amount(self):
|
||||
return self.database_apps.count()
|
||||
|
||||
@lazyproperty
|
||||
def system_users_amount(self):
|
||||
return self.system_users.count()
|
||||
|
|
|
@ -23,6 +23,10 @@ class RemoteAppPermission(BasePermission):
|
|||
def get_all_remote_apps(self):
|
||||
return set(self.remote_apps.all())
|
||||
|
||||
@property
|
||||
def all_remote_apps(self):
|
||||
return self.remote_apps.all()
|
||||
|
||||
@lazyproperty
|
||||
def remote_apps_amount(self):
|
||||
return self.remote_apps.count()
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
from .asset_permission import *
|
||||
from .user_permission import *
|
||||
from .remote_app_permission import *
|
||||
from .remote_app_permission_relation import *
|
||||
from .asset_permission_relation import *
|
||||
from .database_app_permission import *
|
||||
from .database_app_permission_relation import *
|
||||
from .base import *
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
from rest_framework import serializers
|
||||
|
||||
|
||||
class PermissionAllUserSerializer(serializers.Serializer):
|
||||
user = serializers.UUIDField(read_only=True, source='id')
|
||||
user_display = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
only_fields = ['id', 'username', 'name']
|
||||
|
||||
@staticmethod
|
||||
def get_user_display(obj):
|
||||
return str(obj)
|
|
@ -1,6 +1,6 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
from django.db.models import Count
|
||||
from rest_framework import serializers
|
||||
|
||||
from common.fields import StringManyToManyField
|
||||
|
@ -27,13 +27,22 @@ class DatabaseAppPermissionSerializer(BulkOrgResourceModelSerializer):
|
|||
|
||||
|
||||
class DatabaseAppPermissionListSerializer(BulkOrgResourceModelSerializer):
|
||||
users = StringManyToManyField(many=True, read_only=True)
|
||||
user_groups = StringManyToManyField(many=True, read_only=True)
|
||||
database_apps = StringManyToManyField(many=True, read_only=True)
|
||||
system_users = StringManyToManyField(many=True, read_only=True)
|
||||
is_valid = serializers.BooleanField()
|
||||
is_expired = serializers.BooleanField()
|
||||
|
||||
class Meta:
|
||||
model = models.DatabaseAppPermission
|
||||
fields = '__all__'
|
||||
fields = [
|
||||
'id', 'name', 'comment', 'is_active', 'users_amount', 'user_groups_amount',
|
||||
'date_start', 'date_expired', 'is_valid', 'database_apps_amount', 'system_users_amount',
|
||||
'created_by', 'date_created', 'is_expired'
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def setup_eager_loading(cls, queryset):
|
||||
""" Perform necessary eager loading of data. """
|
||||
queryset = queryset.annotate(
|
||||
users_amount=Count('users', distinct=True), user_groups_amount=Count('user_groups', distinct=True),
|
||||
database_apps_amount=Count('database_apps', distinct=True),
|
||||
system_users_amount=Count('system_users', distinct=True)
|
||||
)
|
||||
return queryset
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
from perms.serializers.base import PermissionAllUserSerializer
|
||||
from rest_framework import serializers
|
||||
|
||||
from applications.models import DatabaseApp
|
||||
from common.mixins import BulkSerializerMixin
|
||||
from common.serializers import AdaptedBulkListSerializer
|
||||
|
||||
|
@ -50,16 +50,9 @@ class DatabaseAppPermissionUserGroupRelationSerializer(RelationMixin, serializer
|
|||
]
|
||||
|
||||
|
||||
class DatabaseAppPermissionAllUserSerializer(serializers.Serializer):
|
||||
user = serializers.UUIDField(read_only=True, source='id')
|
||||
user_display = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
only_fields = ['id', 'username', 'name']
|
||||
|
||||
@staticmethod
|
||||
def get_user_display(obj):
|
||||
return str(obj)
|
||||
class DatabaseAppPermissionAllUserSerializer(PermissionAllUserSerializer):
|
||||
class Meta(PermissionAllUserSerializer.Meta):
|
||||
pass
|
||||
|
||||
|
||||
class DatabaseAppPermissionDatabaseAppRelationSerializer(RelationMixin, serializers.ModelSerializer):
|
||||
|
|
|
@ -36,8 +36,8 @@ class RemoteAppPermissionSerializer(BulkOrgResourceModelSerializer):
|
|||
def setup_eager_loading(cls, queryset):
|
||||
""" Perform necessary eager loading of data. """
|
||||
queryset = queryset.annotate(
|
||||
users_amount=Count('users'), user_groups_amount=Count('user_groups'),
|
||||
remote_apps_amount=Count('remote_apps'), system_users_amount=Count('system_users')
|
||||
users_amount=Count('users', distinct=True), user_groups_amount=Count('user_groups', distinct=True),
|
||||
remote_apps_amount=Count('remote_apps', distinct=True), system_users_amount=Count('system_users', distinct=True)
|
||||
)
|
||||
return queryset
|
||||
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
from rest_framework import serializers
|
||||
|
||||
from common.serializers import AdaptedBulkListSerializer
|
||||
from ..models import RemoteAppPermission
|
||||
|
||||
|
||||
__all__ = [
|
||||
'RemoteAppPermissionRemoteAppRelationSerializer',
|
||||
'RemoteAppPermissionAllRemoteAppSerializer',
|
||||
'RemoteAppPermissionUserRelationSerializer',
|
||||
]
|
||||
|
||||
|
||||
class RemoteAppPermissionRemoteAppRelationSerializer(serializers.ModelSerializer):
|
||||
remoteapp_display = serializers.ReadOnlyField()
|
||||
remoteapppermission_display = serializers.ReadOnlyField()
|
||||
|
||||
class Meta:
|
||||
model = RemoteAppPermission.remote_apps.through
|
||||
list_serializer_class = AdaptedBulkListSerializer
|
||||
fields = [
|
||||
'id', 'remoteapp', 'remoteapp_display', 'remoteapppermission', 'remoteapppermission_display'
|
||||
]
|
||||
|
||||
|
||||
class RemoteAppPermissionAllRemoteAppSerializer(serializers.Serializer):
|
||||
remoteapp = serializers.UUIDField(read_only=True, source='id')
|
||||
remoteapp_display = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
only_fields = ['id', 'name']
|
||||
|
||||
@staticmethod
|
||||
def get_remoteapp_display(obj):
|
||||
return str(obj)
|
||||
|
||||
|
||||
class RemoteAppPermissionUserRelationSerializer(serializers.ModelSerializer):
|
||||
user_display = serializers.ReadOnlyField()
|
||||
remoteapppermission_display = serializers.ReadOnlyField()
|
||||
|
||||
class Meta:
|
||||
model = RemoteAppPermission.users.through
|
||||
list_serializer_class = AdaptedBulkListSerializer
|
||||
fields = [
|
||||
'id', 'user', 'user_display', 'remoteapppermission', 'remoteapppermission_display'
|
||||
]
|
|
@ -7,6 +7,9 @@ from .. import api
|
|||
|
||||
router = BulkRouter()
|
||||
router.register('remote-app-permissions', api.RemoteAppPermissionViewSet, 'remote-app-permission')
|
||||
router.register('remote-app-permissions-users-relations', api.RemoteAppPermissionUserRelationViewSet, 'remote-app-permissions-users-relation')
|
||||
router.register('remote-app-permissions-remote-apps-relations', api.RemoteAppPermissionRemoteAppRelationViewSet, 'remote-app-permissions-remote-apps-relation')
|
||||
|
||||
|
||||
remote_app_permission_urlpatterns = [
|
||||
# 查询用户授权的RemoteApp
|
||||
|
@ -32,7 +35,9 @@ remote_app_permission_urlpatterns = [
|
|||
path('remote-app-permissions/<uuid:pk>/users/remove/', api.RemoteAppPermissionRemoveUserApi.as_view(), name='remote-app-permission-remove-user'),
|
||||
path('remote-app-permissions/<uuid:pk>/remote-apps/remove/', api.RemoteAppPermissionRemoveRemoteAppApi.as_view(), name='remote-app-permission-remove-remote-app'),
|
||||
path('remote-app-permissions/<uuid:pk>/remote-apps/add/', api.RemoteAppPermissionAddRemoteAppApi.as_view(), name='remote-app-permission-add-remote-app'),
|
||||
|
||||
path('remote-app-permissions/<uuid:pk>/remote-apps/all/', api.RemoteAppPermissionAllRemoteAppListApi.as_view(), name='remote-app-permission-all-remote-apps'),
|
||||
path('remote-app-permissions/<uuid:pk>/users/all/', api.RemoteAppPermissionAllUserListApi.as_view(), name='remote-app-permission-all-users'),
|
||||
]
|
||||
|
||||
remote_app_permission_urlpatterns += router.urls
|
||||
|
||||
|
|
Loading…
Reference in New Issue