Compare commits

...

8 Commits
v3.7 ... v3.2.1

Author SHA1 Message Date
Bai
893c556b84 perf: ignore 2023-04-24 15:22:16 +08:00
fit2bot
9ca9856a09 feat: Update v3.2.1 2023-04-21 19:15:55 +08:00
feng
ff6a8fa4d7 perf: 开源 acl去除 review 2023-04-21 18:41:26 +08:00
ibuler
802d6136d6 perf: 账号模版 protocols 过滤 2023-04-21 17:11:46 +08:00
ibuler
7e8bb9752c perf: 优化自定义类型的冲突 2023-04-21 15:20:50 +08:00
feng
3fb0197e99 perf: 创建资产 nodes 可为空 默认 default 2023-04-21 14:57:50 +08:00
ibuler
7127b2da93 perf: 去掉 debug msg 2023-04-21 11:32:21 +08:00
ibuler
48b3699591 perf: 优化支持 自定义 applet
perf: 优化平台
2023-04-21 11:31:49 +08:00
18 changed files with 69 additions and 56 deletions

1
GITSHA Normal file
View File

@@ -0,0 +1 @@
ff6a8fa4d774892d7472ff427ac31d82f7c69f0b

View File

@@ -1,13 +1,13 @@
from django_filters import rest_framework as drf_filters
from assets.const import Protocol
from accounts import serializers
from accounts.models import AccountTemplate
from orgs.mixins.api import OrgBulkModelViewSet
from rbac.permissions import RBACPermission
from assets.const import Protocol
from common.drf.filters import BaseFilterSet
from common.permissions import UserConfirmation, ConfirmType
from common.views.mixins import RecordViewLogMixin
from common.drf.filters import BaseFilterSet
from orgs.mixins.api import OrgBulkModelViewSet
from rbac.permissions import RBACPermission
class AccountTemplateFilterSet(BaseFilterSet):
@@ -27,6 +27,8 @@ class AccountTemplateFilterSet(BaseFilterSet):
continue
_st = protocol_secret_type_map[p].get('secret_types', [])
secret_types.update(_st)
if not secret_types:
secret_types = ['password']
queryset = queryset.filter(secret_type__in=secret_types)
return queryset

View File

@@ -28,7 +28,6 @@ class ChangeSecretMixin(models.Model):
default=SSHKeyStrategy.add, verbose_name=_('SSH key change strategy')
)
accounts: list[str] # account usernames
get_all_assets: callable # get all assets
class Meta:

View File

@@ -3,6 +3,7 @@ from rest_framework import serializers
from acls.models.base import ActionChoices
from common.serializers.fields import LabeledChoiceField, ObjectRelatedField
from jumpserver.utils import has_valid_xpack_license
from orgs.models import Organization
from users.models import User
@@ -51,7 +52,26 @@ class ACLAccountsSerializer(serializers.Serializer):
)
class BaseUserAssetAccountACLSerializerMixin(serializers.Serializer):
class ActionAclSerializer(serializers.Serializer):
action = LabeledChoiceField(
choices=ActionChoices.choices, default=ActionChoices.reject, label=_("Action")
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.set_action_choices()
def set_action_choices(self):
action = self.fields.get("action")
if not action:
return
choices = action.choices
if not has_valid_xpack_license():
choices.pop(ActionChoices.review, None)
action._choices = choices
class BaseUserAssetAccountACLSerializerMixin(ActionAclSerializer, serializers.Serializer):
users = ACLUsersSerializer(label=_('User'))
assets = ACLAssestsSerializer(label=_('Asset'))
accounts = ACLAccountsSerializer(label=_('Account'))
@@ -77,9 +97,6 @@ class BaseUserAssetAccountACLSerializerMixin(serializers.Serializer):
reviewers_amount = serializers.IntegerField(
read_only=True, source="reviewers.count", label=_('Reviewers amount')
)
action = LabeledChoiceField(
choices=ActionChoices.choices, default=ActionChoices.reject, label=_("Action")
)
class Meta:
fields_mini = ["id", "name"]

View File

@@ -2,12 +2,11 @@ from django.utils.translation import ugettext as _
from rest_framework import serializers
from common.serializers import BulkModelSerializer, MethodSerializer
from common.serializers.fields import ObjectRelatedField, LabeledChoiceField
from jumpserver.utils import has_valid_xpack_license
from common.serializers.fields import ObjectRelatedField
from users.models import User
from .base import ActionAclSerializer
from .rules import RuleSerializer
from ..models import LoginACL
from ..models.base import ActionChoices
__all__ = [
"LoginACLSerializer",
@@ -18,12 +17,11 @@ common_help_text = _(
)
class LoginACLSerializer(BulkModelSerializer):
class LoginACLSerializer(ActionAclSerializer, BulkModelSerializer):
user = ObjectRelatedField(queryset=User.objects, label=_("User"))
reviewers = ObjectRelatedField(
queryset=User.objects, label=_("Reviewers"), many=True, required=False
)
action = LabeledChoiceField(choices=ActionChoices.choices, label=_('Action'))
reviewers_amount = serializers.IntegerField(
read_only=True, source="reviewers.count", label=_("Reviewers amount")
)
@@ -45,18 +43,5 @@ class LoginACLSerializer(BulkModelSerializer):
"is_active": {"default": True},
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.set_action_choices()
def set_action_choices(self):
action = self.fields.get("action")
if not action:
return
choices = action.choices
if not has_valid_xpack_license():
choices.pop(LoginACL.ActionChoices.review, None)
action._choices = choices
def get_rules_serializer(self):
return RuleSerializer()

View File

@@ -3,6 +3,7 @@ from rest_framework.decorators import action
from rest_framework.response import Response
from common.api import JMSGenericViewSet
from common.permissions import IsValidUser
from assets.serializers import CategorySerializer, TypeSerializer
from assets.const import AllTypes
@@ -14,7 +15,7 @@ class CategoryViewSet(ListModelMixin, JMSGenericViewSet):
'default': CategorySerializer,
'types': TypeSerializer
}
permission_classes = ()
permission_classes = (IsValidUser,)
def get_queryset(self):
return AllTypes.categories()

View File

@@ -57,11 +57,23 @@ class SerializeToTreeNodeMixin:
]
return data
@lazyproperty
def support_types(self):
from assets.const import AllTypes
return AllTypes.get_types_values(exclude_custom=True)
def get_icon(self, asset):
if asset.type in self.support_types:
return asset.type
else:
return 'file'
@timeit
def serialize_assets(self, assets, node_key=None):
sftp_enabled_platform = PlatformProtocol.objects \
.filter(name='ssh', setting__sftp_enabled=True) \
.values_list('platform', flat=True).distinct()
.values_list('platform', flat=True) \
.distinct()
if node_key is None:
get_pid = lambda asset: getattr(asset, 'parent_key', '')
else:
@@ -75,7 +87,7 @@ class SerializeToTreeNodeMixin:
'pId': get_pid(asset),
'isParent': False,
'open': False,
'iconSkin': asset.type,
'iconSkin': self.get_icon(asset),
'chkDisabled': not asset.is_active,
'meta': {
'type': 'asset',

View File

@@ -40,7 +40,6 @@ def get_platform_automation_methods(path):
continue
with open(path, 'r') as f:
print("path: ", path)
manifest = yaml_load_with_i18n(f)
check_platform_method(manifest, path)
manifest['dir'] = os.path.dirname(path)

View File

@@ -8,7 +8,7 @@ class CustomTypes(BaseType):
platforms = list(cls.get_custom_platforms())
except Exception:
return []
types = [p.type for p in platforms]
types = set([p.type for p in platforms])
return [(t, t) for t in types]
@classmethod
@@ -48,11 +48,7 @@ class CustomTypes(BaseType):
@classmethod
def internal_platforms(cls):
return {
# cls.PUBLIC: [],
# cls.PRIVATE: [{'name': 'Vmware-vSphere'}],
# cls.K8S: [{'name': 'Kubernetes'}],
}
return {}
@classmethod
def get_custom_platforms(cls):

View File

@@ -151,15 +151,18 @@ class AllTypes(ChoicesMixin):
)
@classmethod
def get_types(cls):
def get_types(cls, exclude_custom=False):
choices = []
for i in dict(cls.category_types()).values():
choices.extend(i.get_types())
for name, tp in dict(cls.category_types()).items():
if name == Category.CUSTOM and exclude_custom:
continue
choices.extend(tp.get_types())
return choices
@classmethod
def get_types_values(cls):
choices = cls.get_types()
def get_types_values(cls, exclude_custom=False):
choices = cls.get_types(exclude_custom=exclude_custom)
return [c.value for c in choices]
@staticmethod

View File

@@ -145,6 +145,7 @@ class AssetSerializer(BulkOrgResourceModelSerializer, WritableNestedModelSeriali
'name': {'label': _("Name")},
'address': {'label': _('Address')},
'nodes_display': {'label': _('Node path')},
'nodes': {'allow_empty': True},
}
def __init__(self, *args, **kwargs):

View File

@@ -2,7 +2,7 @@ from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
from assets.const.web import FillType
from common.serializers import WritableNestedModelSerializer
from common.serializers import WritableNestedModelSerializer, type_field_map
from common.serializers.fields import LabeledChoiceField
from common.utils import lazyproperty
from ..const import Category, AllTypes
@@ -88,14 +88,7 @@ class PlatformProtocolSerializer(serializers.ModelSerializer):
class PlatformCustomField(serializers.Serializer):
TYPE_CHOICES = [
("str", "str"),
("text", "text"),
("int", "int"),
("bool", "bool"),
("choice", "choice"),
("list", "list"),
]
TYPE_CHOICES = [(t, t) for t, c in type_field_map.items()]
name = serializers.CharField(label=_("Name"), max_length=128)
label = serializers.CharField(label=_("Label"), max_length=128)
type = serializers.ChoiceField(choices=TYPE_CHOICES, label=_("Type"), default='str')

View File

@@ -7,6 +7,7 @@ example_info = [
type_field_map = {
"str": serializers.CharField,
"password": serializers.CharField,
"int": serializers.IntegerField,
"bool": serializers.BooleanField,
"text": serializers.CharField,
@@ -27,6 +28,8 @@ def set_default_if_need(data, i):
def set_default_by_type(tp, data, field_info):
if tp == 'str':
data['max_length'] = 4096
elif tp == 'password':
data['write_only'] = True
elif tp == 'choice':
choices = field_info.pop('choices', [])
if isinstance(choices, str):

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2dd0610d610c2660f35d50dc2871ac08cc09080d2503e1080a57d97c47fea471
size 114418
oid sha256:591b458d6f8ea8d125bd584ca57768cd5aa5a7103b42e345eaadac744a73d475
size 114412

View File

@@ -1060,7 +1060,7 @@ msgstr "Web"
#: assets/const/category.py:15
msgid "Custom type"
msgstr "自定义类型"
msgstr "自定义"
#: assets/const/cloud.py:7
msgid "Public cloud"

View File

@@ -123,7 +123,7 @@ class AssetPermissionSerializer(BulkOrgResourceModelSerializer):
for i in range(0, len(account_ids), slice_count):
push_accounts_to_assets_task.delay(account_ids[i:i + slice_count])
def validate_accounts(self, usernames: list[str]):
def validate_accounts(self, usernames):
template_ids = []
account_usernames = []
for username in usernames:

View File

@@ -98,7 +98,7 @@ class Applet(JMSBaseModel):
return
try:
with open(os.path.join(d, 'platform.yml')) as f:
data = yaml.safe_load(f)
data = yaml_load_with_i18n(f)
except Exception as e:
raise ValidationError({'error': _('Load platform.yml failed: {}').format(e)})

View File

@@ -22,3 +22,4 @@ EOF
}
disable_user_mfa