Compare commits

...

9 Commits
v3.2.0 ... v3.2

8 changed files with 50 additions and 35 deletions

View File

@@ -3,6 +3,7 @@ from rest_framework import serializers
from acls.models.base import ActionChoices from acls.models.base import ActionChoices
from common.serializers.fields import LabeledChoiceField, ObjectRelatedField from common.serializers.fields import LabeledChoiceField, ObjectRelatedField
from jumpserver.utils import has_valid_xpack_license
from orgs.models import Organization from orgs.models import Organization
from users.models import User 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')) users = ACLUsersSerializer(label=_('User'))
assets = ACLAssestsSerializer(label=_('Asset')) assets = ACLAssestsSerializer(label=_('Asset'))
accounts = ACLAccountsSerializer(label=_('Account')) accounts = ACLAccountsSerializer(label=_('Account'))
@@ -77,9 +97,6 @@ class BaseUserAssetAccountACLSerializerMixin(serializers.Serializer):
reviewers_amount = serializers.IntegerField( reviewers_amount = serializers.IntegerField(
read_only=True, source="reviewers.count", label=_('Reviewers amount') read_only=True, source="reviewers.count", label=_('Reviewers amount')
) )
action = LabeledChoiceField(
choices=ActionChoices.choices, default=ActionChoices.reject, label=_("Action")
)
class Meta: class Meta:
fields_mini = ["id", "name"] fields_mini = ["id", "name"]

View File

@@ -2,12 +2,11 @@ from django.utils.translation import ugettext as _
from rest_framework import serializers from rest_framework import serializers
from common.serializers import BulkModelSerializer, MethodSerializer from common.serializers import BulkModelSerializer, MethodSerializer
from common.serializers.fields import ObjectRelatedField, LabeledChoiceField from common.serializers.fields import ObjectRelatedField
from jumpserver.utils import has_valid_xpack_license
from users.models import User from users.models import User
from .base import ActionAclSerializer
from .rules import RuleSerializer from .rules import RuleSerializer
from ..models import LoginACL from ..models import LoginACL
from ..models.base import ActionChoices
__all__ = [ __all__ = [
"LoginACLSerializer", "LoginACLSerializer",
@@ -18,12 +17,11 @@ common_help_text = _(
) )
class LoginACLSerializer(BulkModelSerializer): class LoginACLSerializer(ActionAclSerializer, BulkModelSerializer):
user = ObjectRelatedField(queryset=User.objects, label=_("User")) user = ObjectRelatedField(queryset=User.objects, label=_("User"))
reviewers = ObjectRelatedField( reviewers = ObjectRelatedField(
queryset=User.objects, label=_("Reviewers"), many=True, required=False queryset=User.objects, label=_("Reviewers"), many=True, required=False
) )
action = LabeledChoiceField(choices=ActionChoices.choices, label=_('Action'))
reviewers_amount = serializers.IntegerField( reviewers_amount = serializers.IntegerField(
read_only=True, source="reviewers.count", label=_("Reviewers amount") read_only=True, source="reviewers.count", label=_("Reviewers amount")
) )
@@ -45,18 +43,5 @@ class LoginACLSerializer(BulkModelSerializer):
"is_active": {"default": True}, "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): def get_rules_serializer(self):
return RuleSerializer() return RuleSerializer()

View File

@@ -163,8 +163,10 @@ class CategoryTreeApi(SerializeToTreeNodeMixin, generics.ListAPIView):
# 资源数量统计可选项 (asset, account) # 资源数量统计可选项 (asset, account)
count_resource = self.request.query_params.get('count_resource', 'asset') count_resource = self.request.query_params.get('count_resource', 'asset')
if include_asset and self.request.query_params.get('key'): if not self.request.query_params.get('key'):
nodes = AllTypes.to_tree_nodes(include_asset, count_resource=count_resource)
elif include_asset:
nodes = self.get_assets() nodes = self.get_assets()
else: else:
nodes = AllTypes.to_tree_nodes(include_asset, count_resource=count_resource) nodes = []
return Response(data=nodes) return Response(data=nodes)

View File

@@ -20,12 +20,13 @@ def get_prop_name_id(apps, app, category):
def migrate_database_to_asset(apps, *args): def migrate_database_to_asset(apps, *args):
node_model = apps.get_model('assets', 'Node')
app_model = apps.get_model('applications', 'Application') app_model = apps.get_model('applications', 'Application')
db_model = apps.get_model('assets', 'Database') db_model = apps.get_model('assets', 'Database')
platform_model = apps.get_model('assets', 'Platform') platform_model = apps.get_model('assets', 'Platform')
applications = app_model.objects.filter(category='db') applications = app_model.objects.filter(category='db')
platforms = platform_model.objects.all().filter(internal=True) platforms = platform_model.objects.all().filter(internal=True).exclude(name='Redis6+')
platforms_map = {p.type: p for p in platforms} platforms_map = {p.type: p for p in platforms}
print() print()
@@ -84,11 +85,18 @@ def create_app_nodes(apps, org_id):
node_keys = node_model.objects.filter(org_id=org_id) \ node_keys = node_model.objects.filter(org_id=org_id) \
.filter(key__regex=child_pattern) \ .filter(key__regex=child_pattern) \
.values_list('key', flat=True) .values_list('key', flat=True)
if not node_keys: if node_keys:
return
node_key_split = [key.split(':') for key in node_keys] node_key_split = [key.split(':') for key in node_keys]
next_value = max([int(k[1]) for k in node_key_split]) + 1 next_value = max([int(k[1]) for k in node_key_split]) + 1
parent_key = node_key_split[0][0] parent_key = node_key_split[0][0]
else:
root_node = node_model.objects.filter(org_id=org_id)\
.filter(parent_key='', key__regex=r'^[0-9]+$').exclude(key__startswith='-').first()
if not root_node:
return
parent_key = root_node.key
next_value = 0
next_key = '{}:{}'.format(parent_key, next_value) next_key = '{}:{}'.format(parent_key, next_value)
name = 'Apps' name = 'Apps'
parent = node_model.objects.get(key=parent_key) parent = node_model.objects.get(key=parent_key)

View File

@@ -161,11 +161,12 @@ def migrate_db_accounts(apps, schema_editor):
name = f'{username}(token)' name = f'{username}(token)'
else: else:
secret_type = attr secret_type = attr
name = username name = username or f'{username}(password)'
auth_infos.append((name, secret_type, secret)) auth_infos.append((name, secret_type, secret))
if not auth_infos: if not auth_infos:
auth_infos.append((username, 'password', '')) name = username or f'{username}(password)'
auth_infos.append((name, 'password', ''))
for name, secret_type, secret in auth_infos: for name, secret_type, secret in auth_infos:
values['name'] = name values['name'] = name

View File

@@ -175,6 +175,8 @@ def _parse_ssh_private_key(text, password=None):
dsa.DSAPrivateKey, dsa.DSAPrivateKey,
ed25519.Ed25519PrivateKey, ed25519.Ed25519PrivateKey,
""" """
if not bool(password):
password = None
if isinstance(text, str): if isinstance(text, str):
try: try:
text = text.encode("utf-8") text = text.encode("utf-8")

View File

@@ -80,7 +80,7 @@ def on_org_create_or_update(sender, instance, **kwargs):
@receiver(pre_delete, sender=Organization) @receiver(pre_delete, sender=Organization)
def on_org_delete(sender, instance, **kwargs): def delete_org_root_node_on_org_delete(sender, instance, **kwargs):
expire_orgs_mapping_for_memory(instance.id) expire_orgs_mapping_for_memory(instance.id)
# 删除该组织下所有 节点 # 删除该组织下所有 节点
@@ -91,7 +91,7 @@ def on_org_delete(sender, instance, **kwargs):
@receiver(post_delete, sender=Organization) @receiver(post_delete, sender=Organization)
def on_org_delete(sender, instance, **kwargs): def expire_user_orgs_on_org_delete(sender, instance, **kwargs):
expire_user_orgs() expire_user_orgs()

View File

@@ -140,7 +140,7 @@ class ComponentsPrometheusMetricsUtil(TypedComponentsStatusMetricsUtil):
for component in self.components: for component in self.components:
if not component.is_alive: if not component.is_alive:
continue continue
component_stat = component.latest_stat component_stat = component.last_stat
if not component_stat: if not component_stat:
continue continue
metric_text = state_metric_text % ( metric_text = state_metric_text % (