Browse Source

pref: 优化 permission actionss

pull/9075/head
ibuler 2 years ago
parent
commit
9c5b3a03c6
  1. 16
      apps/common/db/fields.py
  2. 12
      apps/common/drf/fields.py
  3. 62
      apps/common/drf/metadata.py
  4. 67
      apps/perms/const.py

16
apps/common/db/fields.py

@ -2,10 +2,10 @@
#
import json
from django.core.validators import MinValueValidator, MaxValueValidator
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.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],
}

12
apps/common/drf/fields.py

@ -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)

62
apps/common/drf/metadata.py

@ -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)

67
apps/perms/const.py

@ -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…
Cancel
Save