mirror of https://github.com/jumpserver/jumpserver
pref: 优化 permission actionss
parent
1cd551e692
commit
9c5b3a03c6
|
@ -2,10 +2,10 @@
|
|||
#
|
||||
import json
|
||||
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.encoding import force_text
|
||||
from django.core.validators import MinValueValidator, MaxValueValidator
|
||||
from django.db import models
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from common.utils import signer, crypto
|
||||
|
||||
|
@ -211,22 +211,28 @@ class BitChoices(models.IntegerChoices):
|
|||
def branches(cls):
|
||||
return [i for i in cls]
|
||||
|
||||
@classmethod
|
||||
def is_tree(cls):
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def tree(cls):
|
||||
if not cls.is_tree():
|
||||
return []
|
||||
root = [_("All"), cls.branches()]
|
||||
return cls.render_node(root)
|
||||
return [cls.render_node(root)]
|
||||
|
||||
@classmethod
|
||||
def render_node(cls, node):
|
||||
if isinstance(node, BitChoices):
|
||||
return {
|
||||
"id": node.name,
|
||||
"value": node.name,
|
||||
"label": node.label,
|
||||
}
|
||||
else:
|
||||
name, children = node
|
||||
return {
|
||||
"id": name,
|
||||
"value": name,
|
||||
"label": name,
|
||||
"children": [cls.render_node(child) for child in children],
|
||||
}
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
#
|
||||
import six
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.db.models import IntegerChoices
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
from rest_framework.fields import ChoiceField
|
||||
|
||||
from common.db.fields import BitChoices
|
||||
from common.utils import decrypt_password
|
||||
|
||||
__all__ = [
|
||||
|
@ -15,6 +15,7 @@ __all__ = [
|
|||
"LabeledChoiceField",
|
||||
"ObjectRelatedField",
|
||||
"BitChoicesField",
|
||||
"TreeChoicesMixin"
|
||||
]
|
||||
|
||||
|
||||
|
@ -102,14 +103,19 @@ class ObjectRelatedField(serializers.RelatedField):
|
|||
self.fail("incorrect_type", data_type=type(pk).__name__)
|
||||
|
||||
|
||||
class BitChoicesField(serializers.MultipleChoiceField):
|
||||
class TreeChoicesMixin:
|
||||
tree = []
|
||||
|
||||
|
||||
class BitChoicesField(TreeChoicesMixin, serializers.MultipleChoiceField):
|
||||
"""
|
||||
位字段
|
||||
"""
|
||||
|
||||
def __init__(self, choice_cls, **kwargs):
|
||||
assert issubclass(choice_cls, IntegerChoices)
|
||||
assert issubclass(choice_cls, BitChoices)
|
||||
choices = [(c.name, c.label) for c in choice_cls]
|
||||
self.tree = choice_cls.tree()
|
||||
self._choice_cls = choice_cls
|
||||
super().__init__(choices=choices, **kwargs)
|
||||
|
||||
|
|
|
@ -13,6 +13,8 @@ from rest_framework.fields import empty
|
|||
from rest_framework.metadata import SimpleMetadata
|
||||
from rest_framework.request import clone_request
|
||||
|
||||
from common.drf.fields import TreeChoicesMixin
|
||||
|
||||
|
||||
class SimpleMetadataWithFilters(SimpleMetadata):
|
||||
"""Override SimpleMetadata, adding info about filters"""
|
||||
|
@ -59,13 +61,45 @@ class SimpleMetadataWithFilters(SimpleMetadata):
|
|||
view.request = request
|
||||
return actions
|
||||
|
||||
def get_field_type(self, field):
|
||||
"""
|
||||
Given a field, return a string representing the type of the field.
|
||||
"""
|
||||
tp = self.label_lookup[field]
|
||||
|
||||
class_name = field.__class__.__name__
|
||||
if class_name == "LabeledChoiceField":
|
||||
tp = "labeled_choice"
|
||||
elif class_name == "ObjectRelatedField":
|
||||
tp = "object_related_field"
|
||||
elif class_name == "ManyRelatedField":
|
||||
child_relation_class_name = field.child_relation.__class__.__name__
|
||||
if child_relation_class_name == "ObjectRelatedField":
|
||||
tp = "m2m_related_field"
|
||||
return tp
|
||||
|
||||
@staticmethod
|
||||
def set_choices_field(field, field_info):
|
||||
field_info["choices"] = [
|
||||
{
|
||||
"value": choice_value,
|
||||
"label": force_text(choice_label, strings_only=True),
|
||||
}
|
||||
for choice_value, choice_label in dict(field.choices).items()
|
||||
]
|
||||
|
||||
@staticmethod
|
||||
def set_tree_field(field, field_info):
|
||||
field_info["tree"] = field.tree
|
||||
field_info["type"] = "tree"
|
||||
|
||||
def get_field_info(self, field):
|
||||
"""
|
||||
Given an instance of a serializer field, return a dictionary
|
||||
of metadata about it.
|
||||
"""
|
||||
field_info = OrderedDict()
|
||||
field_info["type"] = self.label_lookup[field]
|
||||
field_info["type"] = self.get_field_type(field)
|
||||
field_info["required"] = getattr(field, "required", False)
|
||||
|
||||
# Default value
|
||||
|
@ -84,25 +118,10 @@ class SimpleMetadataWithFilters(SimpleMetadata):
|
|||
elif getattr(field, "fields", None):
|
||||
field_info["children"] = self.get_serializer_info(field)
|
||||
|
||||
is_choice_field = isinstance(field, (serializers.ChoiceField,))
|
||||
if is_choice_field and hasattr(field, "choices"):
|
||||
field_info["choices"] = [
|
||||
{
|
||||
"value": choice_value,
|
||||
"label": force_text(choice_label, strings_only=True),
|
||||
}
|
||||
for choice_value, choice_label in dict(field.choices).items()
|
||||
]
|
||||
|
||||
class_name = field.__class__.__name__
|
||||
if class_name == "LabeledChoiceField":
|
||||
field_info["type"] = "labeled_choice"
|
||||
elif class_name == "ObjectRelatedField":
|
||||
field_info["type"] = "object_related_field"
|
||||
elif class_name == "ManyRelatedField":
|
||||
child_relation_class_name = field.child_relation.__class__.__name__
|
||||
if child_relation_class_name == "ObjectRelatedField":
|
||||
field_info["type"] = "m2m_related_field"
|
||||
if isinstance(field, TreeChoicesMixin):
|
||||
self.set_tree_field(field, field_info)
|
||||
elif isinstance(field, serializers.ChoiceField):
|
||||
self.set_choices_field(field, field_info)
|
||||
return field_info
|
||||
|
||||
@staticmethod
|
||||
|
@ -130,7 +149,8 @@ class SimpleMetadataWithFilters(SimpleMetadata):
|
|||
fields = list(fields.keys())
|
||||
return fields
|
||||
|
||||
def get_ordering_fields(self, request, view):
|
||||
@staticmethod
|
||||
def get_ordering_fields(request, view):
|
||||
fields = []
|
||||
if hasattr(view, "get_ordering_fields"):
|
||||
fields = view.get_ordering_fields(request)
|
||||
|
|
|
@ -3,69 +3,30 @@
|
|||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from common.utils.integer import bit
|
||||
from common.db.fields import BitChoices
|
||||
from common.utils.integer import bit
|
||||
|
||||
|
||||
__all__ = ['SpecialAccount', 'ActionChoices']
|
||||
__all__ = ["SpecialAccount", "ActionChoices"]
|
||||
|
||||
|
||||
class ActionChoices(BitChoices):
|
||||
connect = bit(0), _('Connect')
|
||||
upload = bit(1), _('Upload')
|
||||
download = bit(2), _('Download')
|
||||
copy = bit(3), _('Copy')
|
||||
paste = bit(4), _('Paste')
|
||||
connect = bit(0), _("Connect")
|
||||
upload = bit(1), _("Upload")
|
||||
download = bit(2), _("Download")
|
||||
copy = bit(3), _("Copy")
|
||||
paste = bit(4), _("Paste")
|
||||
|
||||
@classmethod
|
||||
def is_tree(cls):
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
def branches(cls):
|
||||
return (
|
||||
(_('Transfer'), [cls.upload, cls.download]),
|
||||
(_('Clipboard'), [cls.copy, cls.paste]),
|
||||
(_("Transfer"), [cls.upload, cls.download]),
|
||||
(_("Clipboard"), [cls.copy, cls.paste]),
|
||||
)
|
||||
|
||||
|
||||
# class Action(BitOperationChoice):
|
||||
# CONNECT = 0b1
|
||||
# UPLOAD = 0b1 << 1
|
||||
# DOWNLOAD = 0b1 << 2
|
||||
# COPY = 0b1 << 3
|
||||
# PASTE = 0b1 << 4
|
||||
# ALL = 0 << 8
|
||||
# TRANSFER = UPLOAD | DOWNLOAD
|
||||
# CLIPBOARD = COPY | PASTE
|
||||
#
|
||||
# DB_CHOICES = (
|
||||
# (ALL, _('All')),
|
||||
# (CONNECT, _('Connect')),
|
||||
# (UPLOAD, _('Upload file')),
|
||||
# (DOWNLOAD, _('Download file')),
|
||||
# (TRANSFER, _("Upload download")),
|
||||
# (COPY, _('Clipboard copy')),
|
||||
# (PASTE, _('Clipboard paste')),
|
||||
# (CLIPBOARD, _('Clipboard copy paste'))
|
||||
# )
|
||||
#
|
||||
# NAME_MAP = {
|
||||
# ALL: "all",
|
||||
# CONNECT: "connect",
|
||||
# UPLOAD: "upload",
|
||||
# DOWNLOAD: "download",
|
||||
# TRANSFER: "transfer",
|
||||
# COPY: 'copy',
|
||||
# PASTE: 'paste',
|
||||
# CLIPBOARD: 'clipboard'
|
||||
# }
|
||||
#
|
||||
# NAME_MAP_REVERSE = {v: k for k, v in NAME_MAP.items()}
|
||||
# CHOICES = []
|
||||
# for i, j in DB_CHOICES:
|
||||
# CHOICES.append((NAME_MAP[i], j))
|
||||
#
|
||||
# @classmethod
|
||||
# def choices(cls):
|
||||
# pass
|
||||
#
|
||||
|
||||
class SpecialAccount(models.TextChoices):
|
||||
ALL = '@ALL', 'All'
|
||||
ALL = "@ALL", "All"
|
||||
|
|
Loading…
Reference in New Issue