Don't return duplicated users who can create org repo (#22560) (#22562)

- Backport of #22560
- Currently the function `GetUsersWhoCanCreateOrgRepo` uses a query that
is able to have duplicated users in the result, this is can happen under
the condition that a user is in team that either is the owner team or
has permission to create organization repositories.
- Add test code to simulate the above condition for user 3,
[`TestGetUsersWhoCanCreateOrgRepo`](a1fcb1cfb8/models/organization/org_test.go (L435))
is the test function that tests for this.
  - The fix is quite trivial, use a map as a set to get distinct orgs.
tokarchuk/v1.18
Gusted 2 years ago committed by GitHub
parent e6d6bce1f6
commit fd2c250b52
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      models/activities/notification.go
  2. 11
      models/fixtures/team.yml
  3. 6
      models/fixtures/team_user.yml
  4. 2
      models/fixtures/user.yml
  5. 7
      models/organization/org.go
  6. 9
      models/organization/org_test.go

@ -157,7 +157,7 @@ func CreateRepoTransferNotification(doer, newOwner *user_model.User, repo *repo_
} }
for i := range users { for i := range users {
notify = append(notify, &Notification{ notify = append(notify, &Notification{
UserID: users[i].ID, UserID: i,
RepoID: repo.ID, RepoID: repo.ID,
Status: NotificationStatusUnread, Status: NotificationStatusUnread,
UpdatedBy: doer.ID, UpdatedBy: doer.ID,

@ -140,3 +140,14 @@
num_members: 1 num_members: 1
includes_all_repositories: false includes_all_repositories: false
can_create_org_repo: false can_create_org_repo: false
-
id: 14
org_id: 3
lower_name: teamcreaterepo
name: teamCreateRepo
authorize: 2 # write
num_repos: 0
num_members: 1
includes_all_repositories: false
can_create_org_repo: true

@ -93,3 +93,9 @@
org_id: 19 org_id: 19
team_id: 6 team_id: 6
uid: 31 uid: 31
-
id: 17
org_id: 3
team_id: 14
uid: 2

@ -104,7 +104,7 @@
num_following: 0 num_following: 0
num_stars: 0 num_stars: 0
num_repos: 3 num_repos: 3
num_teams: 4 num_teams: 5
num_members: 3 num_members: 3
visibility: 0 visibility: 0
repo_admin_change_team_access: false repo_admin_change_team_access: false

@ -396,13 +396,14 @@ func (org *Organization) GetOrgUserMaxAuthorizeLevel(uid int64) (perm.AccessMode
} }
// GetUsersWhoCanCreateOrgRepo returns users which are able to create repo in organization // GetUsersWhoCanCreateOrgRepo returns users which are able to create repo in organization
func GetUsersWhoCanCreateOrgRepo(ctx context.Context, orgID int64) ([]*user_model.User, error) { func GetUsersWhoCanCreateOrgRepo(ctx context.Context, orgID int64) (map[int64]*user_model.User, error) {
users := make([]*user_model.User, 0, 10) // Use a map, in order to de-duplicate users.
users := make(map[int64]*user_model.User)
return users, db.GetEngine(ctx). return users, db.GetEngine(ctx).
Join("INNER", "`team_user`", "`team_user`.uid=`user`.id"). Join("INNER", "`team_user`", "`team_user`.uid=`user`.id").
Join("INNER", "`team`", "`team`.id=`team_user`.team_id"). Join("INNER", "`team`", "`team`.id=`team_user`.team_id").
Where(builder.Eq{"team.can_create_org_repo": true}.Or(builder.Eq{"team.authorize": perm.AccessModeOwner})). Where(builder.Eq{"team.can_create_org_repo": true}.Or(builder.Eq{"team.authorize": perm.AccessModeOwner})).
And("team_user.org_id = ?", orgID).Asc("`user`.name").Find(&users) And("team_user.org_id = ?", orgID).Find(&users)
} }
// SearchOrganizationsOptions options to filter organizations // SearchOrganizationsOptions options to filter organizations

@ -92,11 +92,12 @@ func TestUser_GetTeams(t *testing.T) {
org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3}) org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3})
teams, err := org.LoadTeams() teams, err := org.LoadTeams()
assert.NoError(t, err) assert.NoError(t, err)
if assert.Len(t, teams, 4) { if assert.Len(t, teams, 5) {
assert.Equal(t, int64(1), teams[0].ID) assert.Equal(t, int64(1), teams[0].ID)
assert.Equal(t, int64(2), teams[1].ID) assert.Equal(t, int64(2), teams[1].ID)
assert.Equal(t, int64(12), teams[2].ID) assert.Equal(t, int64(12), teams[2].ID)
assert.Equal(t, int64(7), teams[3].ID) assert.Equal(t, int64(14), teams[3].ID)
assert.Equal(t, int64(7), teams[4].ID)
} }
} }
@ -293,7 +294,7 @@ func TestUser_GetUserTeamIDs(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, expected, teamIDs) assert.Equal(t, expected, teamIDs)
} }
testSuccess(2, []int64{1, 2}) testSuccess(2, []int64{1, 2, 14})
testSuccess(4, []int64{2}) testSuccess(4, []int64{2})
testSuccess(unittest.NonexistentID, []int64{}) testSuccess(unittest.NonexistentID, []int64{})
} }
@ -448,7 +449,7 @@ func TestGetUsersWhoCanCreateOrgRepo(t *testing.T) {
users, err = organization.GetUsersWhoCanCreateOrgRepo(db.DefaultContext, 7) users, err = organization.GetUsersWhoCanCreateOrgRepo(db.DefaultContext, 7)
assert.NoError(t, err) assert.NoError(t, err)
assert.Len(t, users, 1) assert.Len(t, users, 1)
assert.EqualValues(t, 5, users[0].ID) assert.NotNil(t, users[5])
} }
func TestUser_RemoveOrgRepo(t *testing.T) { func TestUser_RemoveOrgRepo(t *testing.T) {

Loading…
Cancel
Save