Skip to content

Commit

Permalink
feat: 平台管理鉴权调整为无实例 --story=119850967
Browse files Browse the repository at this point in the history
  • Loading branch information
benero committed Oct 3, 2024
1 parent 9d77c88 commit ae2253e
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 41 deletions.
3 changes: 3 additions & 0 deletions itsm/component/drf/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"""
import copy

from django.utils.translation import ugettext as _
from rest_framework import permissions
Expand Down Expand Up @@ -127,6 +128,8 @@ def get_view_iam_actions(view):

if isinstance(apply_actions, str):
apply_actions = [apply_actions]
else:
apply_actions = copy.deepcopy(apply_actions)
return apply_actions

def iam_auth(self, request, apply_actions, obj=None):
Expand Down
16 changes: 13 additions & 3 deletions itsm/component/drf/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def __init__(self, instance=None, data=empty, **kwargs):

self.resource_permissions = {}
if self.instance and self.context.get("request"):
self.resource_permissions = self.get_resource_permission()
self.resource_permissions = self.get_resource_permission() or {}

def get_resource_permission(self):
"""
Expand All @@ -69,7 +69,7 @@ def get_resource_permission(self):
)
resource_type = self.Meta.model.auth_resource.get('resource_type', None)
if resource_type is None:
return []
return {}

instance = instance_list[0]
project_key = DEFAULT_PROJECT_PROJECT_KEY
Expand All @@ -90,7 +90,7 @@ def get_resource_permission(self):
self.Meta.model.resource_operations, resources, project_key=project_key)
except BaseException:
logger.exception("get auth permission error, resource is %s" % resource_type)
return []
return {}

def to_representation(self, instance):
data = super(AuthModelSerializer, self).to_representation(instance)
Expand All @@ -107,6 +107,15 @@ 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 All @@ -132,3 +141,4 @@ def __init__(self, *args, **kwargs):
existing = set(self.fields)
for field_name in existing - allowed:
self.fields.pop(field_name)

53 changes: 21 additions & 32 deletions itsm/workflow/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,51 +176,40 @@ def has_permission(self, request, view):
return UserRole.is_itsm_superuser(request.user.username)


class TemplateFieldPermissionValidate(IamAuthPermit):
class PublicElementManagePermission(IamAuthPermit):
def has_permission(self, request, view):
# 不关联实例的资源,任何请求都要提前鉴权
# 当前系统内,如果没有project_view的权限,无法进入系统
# 免鉴权需要明确声明
if view.action in getattr(view, "permission_free_actions", []):
return True

apply_actions = []
resource_type = getattr(view.queryset.model, "auth_resource", {}).get(
"resource_type"
)


if view.action == "create":
if request.data.get("project_key", None) == PUBLIC_PROJECT_PROJECT_KEY:
apply_actions.append("public_field_create")
project_key = request.data.get("project_key")
if not project_key:
return False

# 平台管理
if project_key == PUBLIC_PROJECT_PROJECT_KEY:
apply_actions = [view.permission_action_platform["create"]]
return self.iam_auth(request, apply_actions)
else:
apply_actions.append("{}_create".format(resource_type))
if "project_key" in request.data:
return self.iam_create_auth(request, apply_actions)

# 项目管理
apply_actions = self.get_view_iam_actions(view)
return self.iam_create_auth(request, apply_actions)

return True

def has_object_permission(self, request, view, obj, **kwargs):
# 关联实例的请求,需要针对对象进行鉴权
if view.action in getattr(view, "permission_free_actions", []):
return True

# 平台管理
if obj.project_key == PUBLIC_PROJECT_PROJECT_KEY:
apply_actions = [view.permission_action_platform["manage"]]
return self.iam_auth(request, apply_actions)

fields_action_map = {
"retrieve": ["field_view"],
"destroy": ["field_delete"],
"update": ["field_edit"],
}

public_fields_action_map = {
"retrieve": ["public_field_view"],
"destroy": ["public_field_delete"],
"update": ["public_field_edit"],
}
apply_actions = []
if view.action in ["retrieve", "destroy", "update"]:
apply_actions = fields_action_map[view.action]
if obj.project_key == PUBLIC_PROJECT_PROJECT_KEY:
apply_actions = public_fields_action_map[view.action]

# 项目管理
apply_actions = self.get_view_iam_actions(view)
return self.iam_auth(request, apply_actions, obj)


Expand Down
1 change: 1 addition & 0 deletions itsm/workflow/serializers/field.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ class Meta:
"project_key",
) + model.FIELDS
read_only_fields = ("is_builtin", "key") + model.FIELDS
create_only_fields = ("is_builtin", "key", )

def __init__(self, *args, **kwargs):
validator_class = kwargs.pop("validator_class", TemplateFieldValidator)
Expand Down
24 changes: 18 additions & 6 deletions itsm/workflow/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,7 @@
WorkflowIamAuth,
FlowVersionIamAuth,
VersionDeletePermit,
TemplateFieldPermissionValidate,
TaskSchemaPermit,
TaskSchemaPermit, PublicElementManagePermission,
)
from itsm.workflow.utils import translate_constant_2, get_notify_type_choice
from itsm.workflow.validators import (
Expand Down Expand Up @@ -740,8 +739,21 @@ class TemplateFieldViewSet(component_viewsets.ModelViewSet):

queryset = TemplateField.objects.all()
serializer_class = TemplateFieldSerializer
# permission_classes = (IamAuthWithoutResourcePermit,)
permission_classes = (TemplateFieldPermissionValidate,)
permission_classes = (PublicElementManagePermission,)
permission_free_actions = ["list", "mix_list"]
# 平台管理
permission_action_platform = {
"create": "public_field_create",
"manage": "public_fields_manage"
}
# 项目管理
permission_action_mapping = {
"create": "field_create",
"retrieve": "field_view",
"destroy": "field_delete",
"update": "field_edit",
}

filter_fields = {
"id": ["in"],
"key": ["exact", "in", "contains", "startswith"],
Expand Down Expand Up @@ -828,6 +840,8 @@ def mix_list(self, request, *args, **kwargs):

def destroy(self, request, *args, **kwargs):
instance = self.get_object()
if instance.is_builtin:
raise ValidationError(_("内置字段不能删除"))

template_field_can_destroy(instance)

Expand Down Expand Up @@ -1024,7 +1038,6 @@ class TransitionTemplateViewSet(BaseWorkflowElementViewSet):
class TableViewSet(component_viewsets.ModelViewSet):
"""基础模型视图"""

# permission_classes = (IamAuthWithoutResourcePermit,)
queryset = Table.objects.filter(is_builtin=True).order_by("-create_at")
serializer_class = TableSerializer
filter_fields = {
Expand Down Expand Up @@ -1156,7 +1169,6 @@ class TaskFieldSchemaViewSet(BaseFieldViewSet):
queryset = TaskFieldSchema.objects.all().order_by("sequence")

serializer_class = TaskFieldSchemaSerializer
# permission_classes = (IamAuthWithoutResourcePermit,)
filter_fields = {
"name": ["exact", "in", "contains"],
"stage": ["exact"],
Expand Down

0 comments on commit ae2253e

Please sign in to comment.