From 28b913f29f812ef51f3b8fe967d5560c1d8ed927 Mon Sep 17 00:00:00 2001 From: kolaente Date: Wed, 4 Mar 2026 19:56:06 +0100 Subject: [PATCH] feat: bypass discoverability settings for external team members --- pkg/user/users_project.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/pkg/user/users_project.go b/pkg/user/users_project.go index 278c2de6f..1ac92dfb5 100644 --- a/pkg/user/users_project.go +++ b/pkg/user/users_project.go @@ -49,6 +49,17 @@ func ListUsers(s *xorm.Session, search string, currentUser *User, opts *ProjectU conds := []builder.Cond{} + // Subquery: find user IDs that share an external team with the current user + externalTeamMemberIDs := builder.Select("tm2.user_id"). + From("team_members tm1"). + Join("INNER", "team_members tm2", "tm1.team_id = tm2.team_id"). + Join("INNER", "teams t", "t.id = tm1.team_id"). + Where(builder.And( + builder.Eq{"tm1.user_id": currentUser.ID}, + builder.Neq{"t.external_id": ""}, + builder.Neq{"tm2.user_id": currentUser.ID}, + )) + queryParts := strings.Split(search, ",") if search != "" { @@ -77,6 +88,14 @@ func ListUsers(s *xorm.Session, search string, currentUser *User, opts *ProjectU db.ILIKE("name", queryPart), builder.Eq{"discoverable_by_name": true}, ), + // External team bypass: match by name or email without discoverability check + builder.And( + builder.In("id", externalTeamMemberIDs), + builder.Or( + db.ILIKE("name", queryPart), + builder.Eq{"email": queryPart}, + ), + ), ) } }