diff --git a/apps/maxkb/settings/base/web.py b/apps/maxkb/settings/base/web.py index d89e28ad8ba..6054f212cd2 100644 --- a/apps/maxkb/settings/base/web.py +++ b/apps/maxkb/settings/base/web.py @@ -48,7 +48,8 @@ 'oss', 'trigger', 'django_apscheduler', - "portal" + "portal", + "django.contrib.postgres" ] MIDDLEWARE = [ diff --git a/apps/portal/migrations/0001_initial.py b/apps/portal/migrations/0001_initial.py index 7753a896e3d..d44df90c6ba 100644 --- a/apps/portal/migrations/0001_initial.py +++ b/apps/portal/migrations/0001_initial.py @@ -7,6 +7,7 @@ def create_default_portal(apps, schema_editor): Portal = apps.get_model("portal", "Portal") Portal.objects.create( + id="019fca92-0371-7a03-a7bb-445ebeb1314c", name="智能体门户", description="默认门户", enable_public_access=True, @@ -28,6 +29,7 @@ class Migration(migrations.Migration): migrations.CreateModel( name='Portal', fields=[ + ('id', models.UUIDField(default=uuid_utils.compat.uuid7, editable=False, primary_key=True, serialize=False, verbose_name='主键id')), ('create_time', models.DateTimeField(auto_now_add=True, db_index=True, verbose_name='创建时间')), ('update_time', models.DateTimeField(auto_now=True, db_index=True, verbose_name='修改时间')), ('name', models.CharField(default='智能体门户', max_length=64, verbose_name='门户名称')), diff --git a/apps/portal/models/portal.py b/apps/portal/models/portal.py index 2b1a03a6d78..631a850f7ec 100644 --- a/apps/portal/models/portal.py +++ b/apps/portal/models/portal.py @@ -10,6 +10,15 @@ class Portal(AppModelMixin): """ 门户配置 """ + + id = models.UUIDField( + primary_key=True, + max_length=128, + default=uuid.uuid7, + editable=False, + verbose_name="主键id" + ) + # 基础信息 name = models.CharField( max_length=64, diff --git a/apps/portal/serializers/portal.py b/apps/portal/serializers/portal.py index e5f48b1e215..8ed80b110b0 100644 --- a/apps/portal/serializers/portal.py +++ b/apps/portal/serializers/portal.py @@ -121,10 +121,9 @@ class Query(serializers.Serializer): help_text=_('Application name')) def get_query_set(self): - queryset = Application.objects.filter(is_publish=True).filter( - id__in=ApplicationAccessToken.objects.filter( - authentication=False - ).values_list('application_id', flat=True) + queryset = Application.objects.filter(is_publish=True).only( + 'id', 'name', 'desc', 'icon', 'type', + 'dialogue_number', 'prologue', 'is_publish', 'create_time' ) name = self.data.get('name') if name: @@ -132,12 +131,17 @@ def get_query_set(self): return queryset.order_by('-create_time') def _apply_auth_filter(self, queryset, user_id): - chat_user_exists = ChatUser.objects.filter( - id=user_id - ).exists() - + chat_user_exists = ChatUser.objects.filter(id=user_id).exists() + public_apps = ApplicationAccessToken.objects.filter( + application_id=OuterRef('id'), + authentication=False + ) if not chat_user_exists: - return queryset + return queryset.filter(Exists(public_apps)) + authed_token_exists = ApplicationAccessToken.objects.filter( + application_id=OuterRef('id'), + authentication=True + ) direct_auth = ResourceChatUserAuthorize.objects.filter( resource_id=OuterRef('id'), resource_type=ResourceType.APPLICATION.value, @@ -153,7 +157,10 @@ def _apply_auth_filter(self, queryset, user_id): is_auth=True, user_group_id__in=user_groups ) - return queryset.filter(Exists(direct_auth) | Exists(group_auth)) + return queryset.filter( + Exists(public_apps) | + (Exists(authed_token_exists) & (Exists(direct_auth) | Exists(group_auth))) + ) def page(self, current_page, page_size, user_id, with_valid=True): if with_valid: diff --git a/apps/users/models/user_group.py b/apps/users/models/user_group.py index c94f36d30aa..138f0e4a91d 100644 --- a/apps/users/models/user_group.py +++ b/apps/users/models/user_group.py @@ -21,7 +21,8 @@ class Meta: class SystemUserGroupRelation(models.Model): id = models.UUIDField(primary_key=True, max_length=128, default=uuid.uuid7, editable=False, verbose_name="主键id") user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="用户") - group = models.ForeignKey(SystemUserGroup, on_delete=models.CASCADE, verbose_name="用户组") + group = models.ForeignKey(SystemUserGroup, on_delete=models.CASCADE, verbose_name="用户组", + related_name="user_relations") class Meta: db_table = "system_user_group_relation" diff --git a/apps/users/serializers/user_group.py b/apps/users/serializers/user_group.py index 50f6573d821..d6bded8a6dd 100644 --- a/apps/users/serializers/user_group.py +++ b/apps/users/serializers/user_group.py @@ -2,8 +2,7 @@ import uuid_utils.compat as uuid from django.db import transaction -from django.db.models import Count, OuterRef, Subquery -from django.db.models.functions import Coalesce +from django.db.models import Count from django.utils.translation import gettext_lazy as _ from rest_framework import serializers @@ -32,9 +31,14 @@ def add_or_edit_user_group_relation(user, user_group_ids): class SystemUserGroupModelSerializer(serializers.ModelSerializer): + count = serializers.SerializerMethodField() + + def get_count(self, obj): + return getattr(obj, 'count', 0) + class Meta: model = SystemUserGroup - fields = ['id', 'name', 'workspace_id'] + fields = ['id', 'name', 'workspace_id', 'count'] class SystemUserGroupCreateSerializer(serializers.Serializer): @@ -101,29 +105,22 @@ def delete(self, *, with_valid=True): self.group.delete() return True - class UserGroupListSerializer(serializers.ModelSerializer): + class Query(serializers.Serializer): workspace_id = serializers.CharField(required=True, label='Workspace ID') - def get_user_groups(self, workspace_id: str): - return list( + def get_query_set(self): + return ( SystemUserGroup.objects - .filter(workspace_id=workspace_id) - .annotate( - count=Coalesce( - Subquery( - SystemUserGroupRelation.objects - .filter(group_id=OuterRef('id')) - .values('group_id') - .annotate(cnt=Count('id')) - .values('cnt') - ), - 0 - ) - ) - .order_by("name") - .values("id", "name", "workspace_id", "count") + .filter(workspace_id=self.data.get('workspace_id')) + .annotate(count=Count('user_relations')) + .order_by('name') ) + def list(self, with_valid=True): + if with_valid: + self.is_valid(raise_exception=True) + return SystemUserGroupModelSerializer(self.get_query_set(), many=True).data + class UserGroupAddMemberSerializer(serializers.Serializer): id = serializers.CharField(required=True, label='ID') diff --git a/apps/users/views/system_user_group.py b/apps/users/views/system_user_group.py index f9b49322fdc..917ff283375 100644 --- a/apps/users/views/system_user_group.py +++ b/apps/users/views/system_user_group.py @@ -80,7 +80,9 @@ def post(self, request: Request, workspace_id: str): ) @has_permissions(PermissionConstants.SYSTEM_USER_GROUP_READ, RoleConstants.ADMIN) def get(self, request: Request, workspace_id: str): - return result.success(SystemUserGroupCreateSerializer.UserGroupListSerializer().get_user_groups(workspace_id)) + return result.success(SystemUserGroupCreateSerializer.Query( + data={'workspace_id': workspace_id} + ).list()) class Delete(APIView): authentication_classes = [TokenAuth]