feat(perms): 添加ApplicationPermission API(包含用户/用户组/授权/校验等API)

pull/4886/head
Bai 4 years ago committed by 老广
parent 4847b7a680
commit 1d550cbe64

@ -1,4 +1,5 @@
from .application import *
from .mixin import *
from .remote_app import *
from .database_app import *
from .k8s_app import *

@ -0,0 +1,49 @@
class SerializeApplicationToTreeNodeMixin:
@staticmethod
def _serialize_db(db):
return {
'id': db.id,
'name': db.name,
'title': db.name,
'pId': '',
'open': False,
'iconSkin': 'database',
'meta': {'type': 'database_app'}
}
@staticmethod
def _serialize_remote_app(remote_app):
return {
'id': remote_app.id,
'name': remote_app.name,
'title': remote_app.name,
'pId': '',
'open': False,
'isParent': False,
'iconSkin': 'chrome',
'meta': {'type': 'remote_app'}
}
@staticmethod
def _serialize_cloud(cloud):
return {
'id': cloud.id,
'name': cloud.name,
'title': cloud.name,
'pId': '',
'open': False,
'isParent': False,
'iconSkin': 'k8s',
'meta': {'type': 'k8s_app'}
}
def dispatch_serialize(self, application):
method_name = f'_serialize_{application.category}'
data = getattr(self, method_name)(application)
return data
def serialize_applications(self, applications):
data = [self.dispatch_serialize(application) for application in applications]
return data

@ -113,3 +113,6 @@ class Application(CommonModelMixin, OrgModelMixin):
class Meta:
unique_together = [('org_id', 'name')]
ordering = ('name',)
def __str__(self):
return '{}({})'.format(self.name, self.get_category_display())

@ -4,9 +4,11 @@
from .asset_permission import *
from .application_permission import *
from .user_permission import *
from .user_permission_application import *
from .asset_permission_relation import *
from .application_permission_relation import *
from .user_group_permission import *
from .user_group_permission_application import *
from .remote_app_permission import *
from .remote_app_permission_relation import *
from .user_remote_app_permission import *

@ -1,18 +1,12 @@
# -*- coding: utf-8 -*-
#
from django.db.models import Q
from common.permissions import IsOrgAdmin
from orgs.mixins.api import OrgModelViewSet
from common.utils import get_object_or_none
from orgs.mixins.api import OrgBulkModelViewSet
from ..models import ApplicationPermission
from ..hands import (
User, UserGroup, Asset, Node, SystemUser,
)
from .. import serializers
class ApplicationPermissionViewSet(OrgModelViewSet):
class ApplicationPermissionViewSet(OrgBulkModelViewSet):
"""
应用授权列表的增删改查API
"""

@ -2,11 +2,10 @@
#
from rest_framework import generics
from django.db.models import F, Value
from django.db.models import Q
from django.db.models.functions import Concat
from django.shortcuts import get_object_or_404
from assets.models import Node, Asset
from applications.models import Application
from orgs.mixins.api import OrgRelationMixin
from orgs.mixins.api import OrgBulkModelViewSet
from orgs.utils import current_org
@ -18,7 +17,9 @@ __all__ = [
'ApplicationPermissionUserRelationViewSet',
'ApplicationPermissionUserGroupRelationViewSet',
'ApplicationPermissionApplicationRelationViewSet',
'ApplicationPermissionSystemUserRelationViewSet'
'ApplicationPermissionSystemUserRelationViewSet',
'ApplicationPermissionAllApplicationListApi',
'ApplicationPermissionAllUserListApi',
]
@ -96,3 +97,32 @@ class ApplicationPermissionSystemUserRelationViewSet(RelationMixin):
Value(')')
))
return queryset
class ApplicationPermissionAllApplicationListApi(generics.ListAPIView):
permission_classes = (IsOrgAdmin,)
serializer_class = serializers.ApplicationPermissionAllApplicationSerializer
only_fields = serializers.ApplicationPermissionAllApplicationSerializer.Meta.only_fields
filter_fields = ('name',)
search_fields = filter_fields
def get_queryset(self):
pk = self.kwargs.get('pk')
perm = get_object_or_404(models.ApplicationPermission, pk=pk)
applications = Application.objects.filter(granted_by_permissions=perm)\
.only(*self.only_fields).distinct()
return applications
class ApplicationPermissionAllUserListApi(generics.ListAPIView):
permission_classes = (IsOrgAdmin,)
serializer_class = serializers.ApplicationPermissionAllUserSerializer
only_fields = serializers.ApplicationPermissionAllUserSerializer.Meta.only_fields
filter_fields = ('username', 'name')
search_fields = filter_fields
def get_queryset(self):
pk = self.kwargs.get('pk')
perm = get_object_or_404(models.ApplicationPermission, pk=pk)
users = perm.get_all_users().only(*self.only_fields).distinct()
return users

@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
#
from django.db.models import Q
from rest_framework.generics import ListAPIView
from common.permissions import IsOrgAdminOrAppUser
from applications.models import Application
from perms import serializers
__all__ = [
'UserGroupGrantedApplicationsApi'
]
class UserGroupGrantedApplicationsApi(ListAPIView):
"""
获取用户组直接授权的资产
"""
permission_classes = (IsOrgAdminOrAppUser,)
serializer_class = serializers.ApplicationGrantedSerializer
only_fields = serializers.ApplicationGrantedSerializer.Meta.only_fields
filter_fields = ['id', 'name', 'comment']
search_fields = ['name', 'comment']
def get_queryset(self):
user_group_id = self.kwargs.get('pk', '')
queryset = Application.objects\
.filter(Q(granted_by_permissions__user_groups__id=user_group_id))\
.distinct().only(*self.only_fields)
return queryset

@ -0,0 +1,2 @@
from .user_permission_applications import *
from .common import *

@ -0,0 +1,75 @@
# -*- coding: utf-8 -*-
#
import uuid
from django.shortcuts import get_object_or_404
from rest_framework.views import APIView, Response
from rest_framework.generics import (
ListAPIView, get_object_or_404
)
from applications.models import Application
from perms.utils.application_permission import (
get_application_system_users_id
)
from perms.api.user_permission.mixin import ForAdminMixin, ForUserMixin
from common.permissions import IsOrgAdminOrAppUser
from ...hands import User, SystemUser
from ... import serializers
__all__ = [
'UserGrantedApplicationSystemUsersApi',
'MyGrantedApplicationSystemUsersApi',
'ValidateUserApplicationPermissionApi'
]
class GrantedApplicationSystemUsersMixin(ListAPIView):
serializer_class = serializers.ApplicationSystemUserSerializer
only_fields = serializers.ApplicationSystemUserSerializer.Meta.only_fields
user: None
def get_application_system_users_id(self, application):
return get_application_system_users_id(self.user, application)
def get_queryset(self):
application_id = self.kwargs.get('application_id')
application = get_object_or_404(Application, id=application_id)
system_users_id = self.get_application_system_users_id(application)
system_users = SystemUser.objects.filter(id__in=system_users_id)\
.only(*self.only_fields).order_by('priority')
return system_users
class UserGrantedApplicationSystemUsersApi(ForAdminMixin, GrantedApplicationSystemUsersMixin):
pass
class MyGrantedApplicationSystemUsersApi(ForUserMixin, GrantedApplicationSystemUsersMixin):
pass
class ValidateUserApplicationPermissionApi(APIView):
permission_classes = (IsOrgAdminOrAppUser,)
def get(self, request, *args, **kwargs):
user_id = request.query_params.get('user_id', '')
application_id = request.query_params.get('application_id', '')
system_user_id = request.query_params.get('system_user_id', '')
try:
user_id = uuid.UUID(user_id)
application_id = uuid.UUID(application_id)
system_user_id = uuid.UUID(system_user_id)
except ValueError:
return Response({'msg': False}, status=403)
user = get_object_or_404(User, id=user_id)
application = get_object_or_404(Application, id=application_id)
system_user = get_object_or_404(SystemUser, id=system_user_id)
system_users_id = get_application_system_users_id(user, application)
if system_user.id in system_users_id:
return Response({'msg': True}, status=200)
return Response({'msg': False}, status=403)

@ -0,0 +1,65 @@
# -*- coding: utf-8 -*-
#
from rest_framework.generics import ListAPIView
from rest_framework.response import Response
from applications.api.mixin import SerializeApplicationToTreeNodeMixin
from perms import serializers
from perms.api.user_permission.mixin import ForAdminMixin, ForUserMixin
from perms.utils.user_application_permission import (
get_user_granted_all_applications
)
__all__ = [
'UserAllGrantedApplicationsApi',
'MyAllGrantedApplicationsApi',
'UserAllGrantedApplicationsAsTreeApi',
'MyAllGrantedApplicationsAsTreeApi',
]
class AllGrantedApplicationsMixin(ListAPIView):
only_fields = serializers.ApplicationGrantedSerializer.Meta.only_fields
serializer_class = serializers.ApplicationGrantedSerializer
filter_fields = ['id', 'name', 'comment']
search_fields = ['name', 'comment']
user: None
def get_queryset(self):
queryset = get_user_granted_all_applications(self.user)
return queryset.only(*self.only_fields)
class UserAllGrantedApplicationsApi(ForAdminMixin, AllGrantedApplicationsMixin):
only_fields = serializers.ApplicationGrantedSerializer.Meta.only_fields
serializer_class = serializers.ApplicationGrantedSerializer
filter_fields = ['id', 'name', 'comment']
search_fields = ['name', 'comment']
def get_queryset(self):
queryset = get_user_granted_all_applications(self.user)
return queryset.only(*self.only_fields)
class MyAllGrantedApplicationsApi(ForUserMixin, AllGrantedApplicationsMixin):
pass
class ApplicationsAsTreeMixin(SerializeApplicationToTreeNodeMixin):
"""
将应用序列化成树的结构返回
"""
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
data = self.serialize_applications(queryset)
return Response(data=data)
class UserAllGrantedApplicationsAsTreeApi(ApplicationsAsTreeMixin, UserAllGrantedApplicationsApi):
pass
class MyAllGrantedApplicationsAsTreeApi(ApplicationsAsTreeMixin, MyAllGrantedApplicationsApi):
pass

@ -2,10 +2,12 @@
#
from django.db import models
from django.db.models import Q
from django.utils.translation import ugettext_lazy as _
from common.utils import lazyproperty
from .base import BasePermission
from users.models import User
__all__ = [
'ApplicationPermission',
@ -36,3 +38,11 @@ class ApplicationPermission(BasePermission):
@lazyproperty
def system_users_amount(self):
return self.system_users.count()
def get_all_users(self):
users_id = self.users.all().values_list('id', flat=True)
user_groups_id = self.user_groups.all().values_list('id', flat=True)
users = User.objects.filter(
Q(id__in=users_id) | Q(groups__id__in=user_groups_id)
)
return users

@ -3,7 +3,6 @@
from rest_framework import serializers
from django.db.models import Count
from orgs.mixins.serializers import BulkOrgResourceModelSerializer
from perms.models import ApplicationPermission

@ -4,15 +4,15 @@ from rest_framework import serializers
from common.mixins import BulkSerializerMixin
from common.serializers import AdaptedBulkListSerializer
from assets.models import Asset, Node
from ..models import ApplicationPermission
from users.models import User
__all__ = [
'ApplicationPermissionUserRelationSerializer',
'ApplicationPermissionUserGroupRelationSerializer',
'ApplicationPermissionApplicationRelationSerializer',
'ApplicationPermissionSystemUserRelationSerializer'
'ApplicationPermissionSystemUserRelationSerializer',
'ApplicationPermissionAllApplicationSerializer',
'ApplicationPermissionAllUserSerializer'
]
@ -67,3 +67,26 @@ class ApplicationPermissionSystemUserRelationSerializer(RelationMixin, serialize
'id', 'systemuser', 'systemuser_display'
]
class ApplicationPermissionAllApplicationSerializer(serializers.Serializer):
application = serializers.UUIDField(read_only=True, source='id')
application_display = serializers.SerializerMethodField()
class Meta:
only_fields = ['id', 'name']
@staticmethod
def get_application_display(obj):
return str(obj)
class ApplicationPermissionAllUserSerializer(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)

@ -7,6 +7,7 @@ from django.utils.translation import ugettext_lazy as _
from assets.models import Node, SystemUser, Asset
from assets.serializers import ProtocolsField
from .asset_permission import ActionsField
from applications.models import Application
__all__ = [
'NodeGrantedSerializer',
@ -15,6 +16,8 @@ __all__ = [
'RemoteAppSystemUserSerializer',
'DatabaseAppSystemUserSerializer',
'K8sAppSystemUserSerializer',
'ApplicationGrantedSerializer',
'ApplicationSystemUserSerializer'
]
@ -34,6 +37,19 @@ class AssetSystemUserSerializer(serializers.ModelSerializer):
read_only_fields = fields
class ApplicationSystemUserSerializer(serializers.ModelSerializer):
"""
查看授权的应用系统用户的数据结构这个和SystemUserSerializer不同字段少
"""
class Meta:
model = SystemUser
only_fields = (
'id', 'name', 'username', 'priority', 'protocol', 'login_mode'
)
fields = list(only_fields)
read_only_fields = fields
class RemoteAppSystemUserSerializer(serializers.ModelSerializer):
class Meta:
model = SystemUser
@ -92,3 +108,16 @@ class NodeGrantedSerializer(serializers.ModelSerializer):
class ActionsSerializer(serializers.Serializer):
actions = ActionsField(read_only=True)
class ApplicationGrantedSerializer(serializers.ModelSerializer):
"""
被授权应用的数据结构
"""
class Meta:
model = Application
only_fields = [
'id', 'name', 'domain', 'category', 'type', 'comment', 'org_id'
]
fields = only_fields + ['org_name']
read_only_fields = fields

@ -13,17 +13,17 @@ router.register('application-permissions-user-groups-relations', api.Application
router.register('application-permissions-applications-relations', api.ApplicationPermissionApplicationRelationViewSet, 'application-permissions-application-relation')
router.register('application-permissions-system-users-relations', api.ApplicationPermissionSystemUserRelationViewSet, 'application-permissions-system-users-relation')
"""
user_permission_urlpatterns = [
path('<uuid:pk>/applications/', api.UserGrantedApplicationsApi.as_view(), name='user-applications'),
path('applications/', api.UserGrantedApplicationsApi.as_view(), name='my-applications'),
path('<uuid:pk>/applications/', api.UserAllGrantedApplicationsApi.as_view(), name='user-applications'),
path('applications/', api.MyAllGrantedApplicationsApi.as_view(), name='my-applications'),
# Application as tree
path('<uuid:pk>/applications/tree/', api.UserGrantedApplicationsAsTreeApi.as_view(), name='user-applications-as-tree'),
path('applications/tree/', api.UserGrantedApplicationsAsTreeApi.as_view(), name='my-applications-as-tree'),
# Application As Tree
path('<uuid:pk>/applications/tree/', api.UserAllGrantedApplicationsAsTreeApi.as_view(), name='user-applications-as-tree'),
path('applications/tree/', api.MyAllGrantedApplicationsAsTreeApi.as_view(), name='my-applications-as-tree'),
# Application System Users
path('<uuid:pk>/applications/<uuid:application_id>/system-users/', api.UserGrantedApplicationSystemUsersApi.as_view(), name='user-application-system-users'),
path('applications/<uuid:application_id>/system-users/', api.UserGrantedApplicationSystemUsersApi.as_view(), name='user-application-system-users'),
path('applications/<uuid:application_id>/system-users/', api.MyGrantedApplicationSystemUsersApi.as_view(), name='my-application-system-users'),
]
user_group_permission_urlpatterns = [
@ -31,11 +31,11 @@ user_group_permission_urlpatterns = [
]
permission_urlpatterns = [
# 授权规则中授权的用户和数据库应用
# 授权规则中授权的用户和应用
path('<uuid:pk>/applications/all/', api.ApplicationPermissionAllApplicationListApi.as_view(), name='application-permission-all-applications'),
path('<uuid:pk>/users/all/', api.ApplicationPermissionAllUserListApi.as_view(), name='application-permission-all-users'),
# 验证用户是否有某个数据库应用的权限
# 验证用户是否有某个应用的权限
path('user/validate/', api.ValidateUserApplicationPermissionApi.as_view(), name='validate-user-application-permission'),
]
@ -46,5 +46,3 @@ application_permission_urlpatterns = [
]
application_permission_urlpatterns += router.urls
"""
application_permission_urlpatterns = router.urls

@ -2,7 +2,9 @@
#
from .asset_permission import *
from .application_permission import *
from .remote_app_permission import *
from .database_app_permission import *
from .k8s_app_permission import *
from .user_asset_permission import *
from .user_application_permission import *

@ -0,0 +1,14 @@
from django.db.models import Q
from common.utils import get_logger
from ..models import ApplicationPermission
logger = get_logger(__file__)
def get_application_system_users_id(user, application):
queryset = ApplicationPermission.objects\
.filter(Q(users=user) | Q(user_groups__users=user), Q(applications=application))\
.valid()\
.values_list('system_users', flat=True)
return queryset

@ -0,0 +1,21 @@
from perms.models import ApplicationPermission
from applications.models import Application
def get_user_all_applicationpermission_ids(user):
application_perm_ids = set()
application_perm_ids.update(
ApplicationPermission.objects.valid().filter(users=user).distinct().values_list('id', flat=True)
)
application_perm_ids.update(
ApplicationPermission.objects.valid().filter(user_groups__users=user).distinct().values_list('id', flat=True)
)
return application_perm_ids
def get_user_granted_all_applications(user):
application_perm_ids = get_user_all_applicationpermission_ids(user)
applications = Application.objects.filter(
granted_by_permissions__id__in=application_perm_ids
).distinct()
return applications
Loading…
Cancel
Save