Compare commits

...

13 Commits

Author SHA1 Message Date
fit2bot
3689bc62ab feat: Update v3.10.3 2024-01-24 17:58:29 +08:00
ibuler
1f1c1a9157 fix: 修复定时检测用户是否活跃任务无法执行的问题 2024-01-23 09:28:38 +00:00
feng
6c9d271ae1 fix: redis 密码有特殊字符celery beat启动失败 2024-01-22 06:18:34 +00:00
Bai
6ff852e225 perf: 修复 Count 时没有去重的问题 2024-01-22 06:16:25 +00:00
Bryan
baa75dc735 Merge pull request #12566 from jumpserver/master
v3.10.2
2024-01-17 07:34:28 -04:00
Bryan
8a9f0436b8 Merge pull request #12565 from jumpserver/dev
v3.10.2
2024-01-17 07:23:30 -04:00
Bryan
a9620a3cbe Merge pull request #12461 from jumpserver/master
v3.10.1
2023-12-29 11:33:05 +05:00
Bryan
769e7dc8a0 Merge pull request #12460 from jumpserver/dev
v3.10.1
2023-12-29 11:20:36 +05:00
Bryan
2a70449411 Merge pull request #12458 from jumpserver/dev
v3.10.1
2023-12-29 11:01:13 +05:00
Bryan
8df720f19e Merge pull request #12401 from jumpserver/dev
v3.10
2023-12-21 15:14:19 +05:00
老广
dabbb45f6e Merge pull request #12144 from jumpserver/dev
v3.9.0
2023-11-16 18:23:05 +08:00
Bryan
ce24c1c3fd Merge pull request #11914 from jumpserver/dev
v3.8.0
2023-10-19 03:37:39 -05:00
Bryan
3c54c82ce9 Merge pull request #11636 from jumpserver/dev
v3.7.0
2023-09-21 17:02:48 +08:00
15 changed files with 32 additions and 24 deletions

1
GITSHA Normal file
View File

@@ -0,0 +1 @@
1f1c1a9157477f07ebfe97ca25b31084da3a67ea

View File

@@ -55,7 +55,7 @@ def clean_historical_accounts():
history_model = Account.history.model
history_id_mapper = defaultdict(list)
ids = history_model.objects.values('id').annotate(count=Count('id')) \
ids = history_model.objects.values('id').annotate(count=Count('id', distinct=True)) \
.filter(count__gte=limit).values_list('id', flat=True)
if not ids:

View File

@@ -58,7 +58,7 @@ class DomainListSerializer(DomainSerializer):
@classmethod
def setup_eager_loading(cls, queryset):
queryset = queryset.annotate(
assets_amount=Count('assets'),
assets_amount=Count('assets', distinct=True),
)
return queryset

View File

@@ -206,7 +206,7 @@ class LabelFilterBackend(filters.BaseFilterBackend):
resources = resources.filter(q) \
.values('res_id') \
.order_by('res_id') \
.annotate(count=Count('res_id')) \
.annotate(count=Count('res_id', distinct=True)) \
.values('res_id', 'count') \
.filter(count=len(args))
return resources

View File

@@ -182,14 +182,14 @@ class DatesLoginMetricMixin:
def get_dates_login_times_assets(self):
assets = self.sessions_queryset.values("asset") \
.annotate(total=Count("asset")) \
.annotate(total=Count("asset", distinct=True)) \
.annotate(last=Cast(Max("date_start"), output_field=CharField())) \
.order_by("-total")
return list(assets[:10])
def get_dates_login_times_users(self):
users = self.sessions_queryset.values("user_id") \
.annotate(total=Count("user_id")) \
.annotate(total=Count("user_id", distinct=True)) \
.annotate(user=Max('user')) \
.annotate(last=Cast(Max("date_start"), output_field=CharField())) \
.order_by("-total")

View File

@@ -8,7 +8,7 @@ __all__ = ['BASE_DIR', 'PROJECT_DIR', 'VERSION', 'CONFIG']
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
PROJECT_DIR = os.path.dirname(BASE_DIR)
VERSION = '2.0.0'
VERSION = 'v3.10.3'
CONFIG = ConfigManager.load_user_config()

View File

@@ -34,7 +34,7 @@ class LabelSerializer(BulkOrgResourceModelSerializer):
@classmethod
def setup_eager_loading(cls, queryset):
""" Perform necessary eager loading of data. """
queryset = queryset.annotate(res_count=Count('labeled_resources'))
queryset = queryset.annotate(res_count=Count('labeled_resources', distinct=True))
return queryset

View File

@@ -246,6 +246,6 @@ class UsernameHintsAPI(APIView):
.filter(username__icontains=query) \
.filter(asset__in=assets) \
.values('username') \
.annotate(total=Count('username')) \
.annotate(total=Count('username', distinct=True)) \
.order_by('total', '-username')[:10]
return Response(data=top_accounts)

View File

@@ -198,9 +198,9 @@ class AssetPermissionListSerializer(AssetPermissionSerializer):
"""Perform necessary eager loading of data."""
queryset = queryset \
.prefetch_related('labels', 'labels__label') \
.annotate(users_amount=Count("users"),
user_groups_amount=Count("user_groups"),
assets_amount=Count("assets"),
nodes_amount=Count("nodes"),
.annotate(users_amount=Count("users", distinct=True),
user_groups_amount=Count("user_groups", distinct=True),
assets_amount=Count("assets", distinct=True),
nodes_amount=Count("nodes", distinct=True),
)
return queryset

View File

@@ -80,9 +80,11 @@ class RoleViewSet(JMSModelViewSet):
queryset = Role.objects.filter(id__in=ids).order_by(*self.ordering)
org_id = current_org.id
q = Q(role__scope=Role.Scope.system) | Q(role__scope=Role.Scope.org, org_id=org_id)
role_bindings = RoleBinding.objects.filter(q).values_list('role_id').annotate(user_count=Count('user_id'))
role_bindings = RoleBinding.objects.filter(q).values_list('role_id').annotate(
user_count=Count('user_id', distinct=True)
)
role_user_amount_mapper = {role_id: user_count for role_id, user_count in role_bindings}
queryset = queryset.annotate(permissions_amount=Count('permissions'))
queryset = queryset.annotate(permissions_amount=Count('permissions', distinct=True))
queryset = list(queryset)
for role in queryset:
role.users_amount = role_user_amount_mapper.get(role.id, 0)

View File

@@ -729,7 +729,7 @@ class JSONFilterMixin:
bindings = RoleBinding.objects.filter(**kwargs, role__in=value)
if match == 'm2m_all':
user_id = bindings.values('user_id').annotate(count=Count('user_id')) \
user_id = bindings.values('user_id').annotate(count=Count('user_id', distinct=True)) \
.filter(count=len(value)).values_list('user_id', flat=True)
else:
user_id = bindings.values_list('user_id', flat=True)

View File

@@ -46,7 +46,7 @@ class UserGroupSerializer(ResourceLabelsMixin, BulkOrgResourceModelSerializer):
def setup_eager_loading(cls, queryset):
""" Perform necessary eager loading of data. """
queryset = queryset.prefetch_related('labels', 'labels__label') \
.annotate(users_amount=Count('users', filter=Q(users__is_service_account=False)))
.annotate(users_amount=Count('users', distinct=True, filter=Q(users__is_service_account=False)))
return queryset

View File

@@ -86,7 +86,7 @@ def check_user_expired_periodic():
@tmp_to_root_org()
def check_unused_users():
uncommon_users_ttl = settings.SECURITY_UNCOMMON_USERS_TTL
if not uncommon_users_ttl or not uncommon_users_ttl.isdigit():
if not uncommon_users_ttl:
return
uncommon_users_ttl = int(uncommon_users_ttl)

View File

@@ -1,6 +1,6 @@
[tool.poetry]
name = "jumpserver"
version = "v3.9"
version = "v3.10.3"
description = "广受欢迎的开源堡垒机"
authors = ["ibuler <ibuler@qq.com>"]
license = "GPLv3"

View File

@@ -1,13 +1,12 @@
#!/usr/bin/env python
#
import os
import sys
import signal
import subprocess
import sys
import redis_lock
from redis import Redis, Sentinel
from redis import Redis, Sentinel, ConnectionPool
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
APPS_DIR = os.path.join(BASE_DIR, 'apps')
@@ -50,9 +49,15 @@ if REDIS_SENTINEL_SERVICE_NAME and REDIS_SENTINELS:
)
redis_client = sentinel_client.master_for(REDIS_SENTINEL_SERVICE_NAME)
else:
connection_params['host'] = settings.REDIS_HOST
connection_params['port'] = settings.REDIS_PORT
redis_client = Redis(**connection_params)
REDIS_PROTOCOL = 'rediss' if settings.REDIS_USE_SSL else 'redis'
REDIS_LOCATION_NO_DB = '%(protocol)s://:%(password)s@%(host)s:%(port)s' % {
'protocol': REDIS_PROTOCOL,
'password': settings.REDIS_PASSWORD,
'host': settings.REDIS_HOST,
'port': settings.REDIS_PORT,
}
pool = ConnectionPool.from_url(REDIS_LOCATION_NO_DB, **connection_params)
redis_client = Redis(connection_pool=pool)
scheduler = "ops.celery.beat.schedulers:DatabaseScheduler"
processes = []