Skip to content

Commit

Permalink
feat: API 平台鉴权调整为无实例 --story=119850967
Browse files Browse the repository at this point in the history
  • Loading branch information
benero committed Oct 3, 2024
1 parent 1ade2e1 commit 094ef5d
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 40 deletions.
23 changes: 13 additions & 10 deletions itsm/component/drf/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,19 @@
from itsm.component.constants import DEFAULT_PROJECT_PROJECT_KEY


class AuthModelSerializer(serializers.ModelSerializer):
class BaseModelSerializer(serializers.ModelSerializer):

def to_internal_value(self, data):
data = super().to_internal_value(data)
if self.instance:
# update
if hasattr(self.Meta, "create_only_fields"):
for x in self.Meta.create_only_fields:
data.pop(x, None)
return data


class AuthModelSerializer(BaseModelSerializer):
"""
权限中心接入每个资源权限内容序列化
"""
Expand Down Expand Up @@ -107,15 +119,6 @@ def update_auth_actions(self, instance, data):
auth_actions=[action for action, result in instance_permissions.items() if result])
return data

def to_internal_value(self, data):
data = super().to_internal_value(data)
if self.instance:
# update
if hasattr(self.Meta, "create_only_fields"):
for x in self.Meta.create_only_fields:
data.pop(x, None)
return data


class DynamicFieldsModelSerializer(AuthModelSerializer):
"""
Expand Down
68 changes: 44 additions & 24 deletions itsm/postman/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,12 @@

from itsm.component.constants import PUBLIC_PROJECT_PROJECT_KEY
from itsm.component.drf import permissions as perm
from itsm.postman.models import RemoteSystem
from itsm.component.exceptions import ValidateError
from itsm.postman.models import RemoteSystem, RemoteApi
from django.utils.translation import ugettext as _

from itsm.project.models import Project
from itsm.workflow.permissions import WorkflowElementManagePermission


class IsObjManager(perm.IsManager):
Expand All @@ -36,37 +41,52 @@ class IsObjManager(perm.IsManager):
pass


class RemoteApiPermit(perm.IamAuthProjectViewPermit):
class RemoteApiPermit(WorkflowElementManagePermission):
def has_permission(self, request, view):
if view.action == "create":
if "remote_system" in request.data:
remote_system_id = request.data["remote_system"]
project_key = RemoteSystem.objects.get(id=remote_system_id).project_key
# 平台公共API管理
if project_key == PUBLIC_PROJECT_PROJECT_KEY:
apply_actions = ["public_api_view"]
return self.iam_auth(request, apply_actions)
else:
# 项目
apply_actions = ["system_settings_manage"]
return self.has_project_view_permission(
request, project_key, apply_actions
)
return self.iam_auth(request, ["public_apis_manage"])

# 项目管理
apply_actions = ["system_settings_manage"]
project = Project.objects.get(pk=project_key)
return self.iam_auth(request, apply_actions, project)

if view.action == "batch_delete":
api_ids = request.data["id"].split(",")
api_instances = RemoteApi.objects.filter(pk__in=api_ids)
project_keys = set([i.remote_system.project_key for i in api_instances])
if len(project_keys) != 1:
raise ValidateError(_("API 所属项目异常"))
project_key = project_keys.pop()

# 平台公共API管理
if project_key == PUBLIC_PROJECT_PROJECT_KEY:
return self.iam_auth(request, ["public_apis_manage"])

# 项目
project = Project.objects.get(pk=project_key)
return self.iam_auth(request, ["system_settings_manage"], project)

return True

def has_object_permission(self, request, view, obj):
if obj is not None:
# 如果是公共api需要单独鉴权
def has_object_permission(self, request, view, obj, **kwargs):
if view.action in getattr(view, "permission_free_actions", []):
return True

if obj:
# 平台公共 API 管理
if obj.remote_system.project_key == PUBLIC_PROJECT_PROJECT_KEY:
if view.action == "retrieve":
apply_actions = []
else:
apply_actions = ["public_api_manage"]
return self.iam_auth(request, apply_actions, obj)
else:
# 项目
project_key = obj.remote_system.project_key
apply_actions = ["system_settings_manage"]
return self.has_project_view_permission(
request, project_key, apply_actions
)
return True
return self.iam_auth(request, ["public_apis_manage"])

# 项目管理
project_key = obj.remote_system.project_key
project = Project.objects.get(pk=project_key)
return self.iam_auth(request, ["system_settings_manage"], project)
return True
6 changes: 4 additions & 2 deletions itsm/postman/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,14 @@
LEN_XX_LONG,
PUBLIC_PROJECT_PROJECT_KEY,
)
from itsm.component.drf.serializers import DynamicFieldsModelSerializer
from itsm.component.drf.serializers import DynamicFieldsModelSerializer, BaseModelSerializer
from itsm.component.exceptions import ParamError
from itsm.component.utils.basic import normal_name, dotted_name
from itsm.postman.models import RemoteApi, RemoteApiInstance, RemoteSystem
from itsm.workflow.models import Field, State


class RemoteSystemSerializer(serializers.ModelSerializer):
class RemoteSystemSerializer(BaseModelSerializer):
"""API系统序列化"""

name = serializers.CharField(
Expand Down Expand Up @@ -90,6 +90,7 @@ class Meta:
"project_key",
)
read_only_fields = ("creator", "updated_by")
create_only_fields = ["project_key"]

def to_internal_value(self, data):
# 新增系统时,system_id为空
Expand Down Expand Up @@ -175,6 +176,7 @@ class Meta:
"is_builtin",
)
read_only_fields = ("creator", "updated_by")
create_only_fields = ["remote_system"]

def to_internal_value(self, data):
data = super(RemoteApiSerializer, self).to_internal_value(data)
Expand Down
22 changes: 20 additions & 2 deletions itsm/postman/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
from itsm.component.constants import ResponseCodeStatus, PUBLIC_PROJECT_PROJECT_KEY
from itsm.component.dlls.component import ComponentLibrary
from itsm.component.drf import viewsets as component_viewsets
from itsm.component.drf.exception import ValidationError
from itsm.component.drf.mixins import DynamicListModelMixin
from itsm.component.drf.permissions import IamAuthProjectViewPermit
from itsm.component.esb.backend_component import bk
Expand All @@ -52,6 +53,7 @@
RemoteApiSerializer,
RemoteSystemSerializer,
)
from itsm.workflow.permissions import WorkflowElementManagePermission


class ModelViewSet(component_viewsets.ModelViewSet):
Expand Down Expand Up @@ -91,8 +93,13 @@ class RemoteSystemViewSet(ModelViewSet):

serializer_class = RemoteSystemSerializer
queryset = RemoteSystem.objects.all()
permission_classes = (IamAuthProjectViewPermit,)
permission_classes = (WorkflowElementManagePermission,)
# 平台管理
permission_action_platform = "public_apis_manage"
# 项目管理
permission_action_default = "system_settings_manage"
permission_free_actions = ["list", "all", "get_systems", "get_components"]

pagination_class = None

filter_fields = {
Expand Down Expand Up @@ -180,7 +187,9 @@ class RemoteApiViewSet(DynamicListModelMixin, ModelViewSet):

serializer_class = RemoteApiSerializer
queryset = RemoteApi.objects.all()

permission_classes = (RemoteApiPermit,)
permission_free_actions = ["retrieve"]

filter_fields = {
"is_activated": ["exact"],
Expand Down Expand Up @@ -244,8 +253,17 @@ def batch_delete(self, request, *args, **kwargs):

will_deleted = self.queryset.filter(id__in=id_list)
real_deleted = list(will_deleted.values_list("id", flat=True))
will_deleted.delete()

# 判断输入的接口实例
if will_deleted.count() != len(real_deleted):
raise ValidationError(_("接口数量异常,请刷新后重试"))

# 检测实例所属项目是否一致
project_keys = [i.remote_system.project_key for i in will_deleted]
if len(set(project_keys)) != 1:
raise ValidationError(_("接口数量异常,请刷新后重试"))

will_deleted.delete()
return Response(real_deleted)

@action(detail=True, methods=["get"])
Expand Down
10 changes: 8 additions & 2 deletions itsm/workflow/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

from itsm.component.constants import PUBLIC_PROJECT_PROJECT_KEY
from itsm.component.drf.permissions import IamAuthPermit
from itsm.project.models import Project
from itsm.role.models import UserRole
from itsm.service.models import Service
from itsm.workflow.models import Workflow
Expand Down Expand Up @@ -195,7 +196,11 @@ def has_permission(self, request, view):
# 项目管理
apply_actions = self.get_view_iam_actions(view)
return self.iam_create_auth(request, apply_actions)


# 有配置权限则按无实例进行鉴权
apply_actions = self.get_view_iam_actions(view)
if apply_actions:
return self.iam_auth(request, apply_actions)
return True

def has_object_permission(self, request, view, obj, **kwargs):
Expand All @@ -210,7 +215,8 @@ def has_object_permission(self, request, view, obj, **kwargs):

# 项目管理
apply_actions = self.get_view_iam_actions(view)
return self.iam_auth(request, apply_actions, obj)
project = Project.objects.get(pk=obj.project_key)
return self.iam_auth(request, apply_actions, project)


class TaskSchemaPermit(IamAuthPermit):
Expand Down

0 comments on commit 094ef5d

Please sign in to comment.