diff --git a/backend/open_webui/models/channels.py b/backend/open_webui/models/channels.py index 215b46ead6..c30e2347b9 100644 --- a/backend/open_webui/models/channels.py +++ b/backend/open_webui/models/channels.py @@ -9,6 +9,7 @@ from open_webui.models.access_grants import ( AccessGrants, ) from open_webui.models.groups import Groups +from open_webui.models.users import User from open_webui.utils.validate import validate_profile_image_url from pydantic import BaseModel, ConfigDict, Field, field_validator from sqlalchemy import ( @@ -437,17 +438,17 @@ class ChannelTable: match_count = func.sum( case( - (ChannelMember.user_id.in_(unique_user_ids), 1), + (User.id.in_(unique_user_ids), 1), else_=0, ) ) subquery = ( select(ChannelMember.channel_id) + .join(User, User.id == ChannelMember.user_id) .group_by(ChannelMember.channel_id) - # 1. Channel must have exactly len(user_ids) members - .having(func.count(ChannelMember.user_id) == len(unique_user_ids)) - # 2. All those members must be in unique_user_ids + # Match the exact set of accounts that still exist. + .having(func.count(User.id) == len(unique_user_ids)) .having(match_count == len(unique_user_ids)) .subquery() ) diff --git a/backend/open_webui/routers/channels.py b/backend/open_webui/routers/channels.py index 225c505532..652cbdf07f 100644 --- a/backend/open_webui/routers/channels.py +++ b/backend/open_webui/routers/channels.py @@ -176,7 +176,7 @@ async def get_channels( user_ids = None users = None if channel.type == 'dm': - user_ids = [member.user_id for member in await Channels.get_members_by_channel_id(channel.id, db=db)] + member_user_ids = [member.user_id for member in await Channels.get_members_by_channel_id(channel.id, db=db)] users = [ UserIdNameStatusResponse( **{ @@ -184,8 +184,9 @@ async def get_channels( 'is_active': Users.is_active(u), } ) - for u in await Users.get_users_by_user_ids(user_ids, db=db) + for u in await Users.get_users_by_user_ids(member_user_ids, db=db) ] + user_ids = [u.id for u in users] channel_list.append( ChannelListItemResponse( @@ -382,7 +383,7 @@ async def get_channel_by_id( if not await Channels.is_user_channel_member(channel.id, user.id, db=db): raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.DEFAULT()) - user_ids = [member.user_id for member in await Channels.get_members_by_channel_id(channel.id, db=db)] + member_user_ids = [member.user_id for member in await Channels.get_members_by_channel_id(channel.id, db=db)] users = [ UserIdNameStatusResponse( @@ -391,8 +392,9 @@ async def get_channel_by_id( 'is_active': Users.is_active(u), } ) - for u in await Users.get_users_by_user_ids(user_ids, db=db) + for u in await Users.get_users_by_user_ids(member_user_ids, db=db) ] + user_ids = [u.id for u in users] channel_member = await Channels.get_member_by_channel_and_user_id(channel.id, user.id, db=db) unread_count = await Messages.get_unread_message_count( @@ -406,7 +408,7 @@ async def get_channel_by_id( 'users': users, 'is_manager': await Channels.is_user_channel_manager(channel.id, user.id, db=db), 'write_access': True, - 'user_count': len(user_ids), + 'user_count': len(users), 'last_read_at': channel_member.last_read_at if channel_member else None, 'unread_count': unread_count, }