mirror of https://github.com/go-gitea/gitea.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
89 lines
3.1 KiB
89 lines
3.1 KiB
// Copyright 2024 The Gitea Authors. All rights reserved. |
|
// SPDX-License-Identifier: MIT |
|
|
|
package pull |
|
|
|
import ( |
|
"context" |
|
|
|
"code.gitea.io/gitea/models/db" |
|
"code.gitea.io/gitea/models/organization" |
|
"code.gitea.io/gitea/models/perm" |
|
repo_model "code.gitea.io/gitea/models/repo" |
|
"code.gitea.io/gitea/models/unit" |
|
user_model "code.gitea.io/gitea/models/user" |
|
"code.gitea.io/gitea/modules/container" |
|
|
|
"xorm.io/builder" |
|
) |
|
|
|
// GetReviewers get all users can be requested to review: |
|
// - Poster should not be listed |
|
// - For collaborator, all users that have read access or higher to the repository. |
|
// - For repository under organization, users under the teams which have read permission or higher of pull request unit |
|
// - Owner will be listed if it's not an organization, not the poster and not in the list of reviewers |
|
func GetReviewers(ctx context.Context, repo *repo_model.Repository, doerID, posterID int64) ([]*user_model.User, error) { |
|
if err := repo.LoadOwner(ctx); err != nil { |
|
return nil, err |
|
} |
|
|
|
e := db.GetEngine(ctx) |
|
uniqueUserIDs := make(container.Set[int64]) |
|
|
|
collaboratorIDs := make([]int64, 0, 10) |
|
if err := e.Table("collaboration").Where("repo_id=?", repo.ID). |
|
And("mode >= ?", perm.AccessModeRead). |
|
Select("user_id"). |
|
Find(&collaboratorIDs); err != nil { |
|
return nil, err |
|
} |
|
uniqueUserIDs.AddMultiple(collaboratorIDs...) |
|
|
|
if repo.Owner.IsOrganization() { |
|
additionalUserIDs := make([]int64, 0, 10) |
|
if err := e.Table("team_user"). |
|
Join("INNER", "team_repo", "`team_repo`.team_id = `team_user`.team_id"). |
|
Join("INNER", "team_unit", "`team_unit`.team_id = `team_user`.team_id"). |
|
Where("`team_repo`.repo_id = ? AND (`team_unit`.access_mode >= ? AND `team_unit`.`type` = ?)", |
|
repo.ID, perm.AccessModeRead, unit.TypePullRequests). |
|
Distinct("`team_user`.uid"). |
|
Select("`team_user`.uid"). |
|
Find(&additionalUserIDs); err != nil { |
|
return nil, err |
|
} |
|
uniqueUserIDs.AddMultiple(additionalUserIDs...) |
|
} |
|
|
|
uniqueUserIDs.Remove(posterID) // posterID should not be in the list of reviewers |
|
|
|
// Leave a seat for owner itself to append later, but if owner is an organization |
|
// and just waste 1 unit is cheaper than re-allocate memory once. |
|
users := make([]*user_model.User, 0, len(uniqueUserIDs)+1) |
|
if len(uniqueUserIDs) > 0 { |
|
if err := e.In("id", uniqueUserIDs.Values()). |
|
Where(builder.Eq{"`user`.is_active": true}). |
|
OrderBy(user_model.GetOrderByName()). |
|
Find(&users); err != nil { |
|
return nil, err |
|
} |
|
} |
|
|
|
// add owner after all users are loaded because we can avoid load owner twice |
|
if repo.OwnerID != posterID && !repo.Owner.IsOrganization() && !uniqueUserIDs.Contains(repo.OwnerID) { |
|
users = append(users, repo.Owner) |
|
} |
|
|
|
return users, nil |
|
} |
|
|
|
// GetReviewerTeams get all teams can be requested to review |
|
func GetReviewerTeams(ctx context.Context, repo *repo_model.Repository) ([]*organization.Team, error) { |
|
if err := repo.LoadOwner(ctx); err != nil { |
|
return nil, err |
|
} |
|
if !repo.Owner.IsOrganization() { |
|
return nil, nil |
|
} |
|
|
|
return organization.GetTeamsWithAccessToAnyRepoUnit(ctx, repo.OwnerID, repo.ID, perm.AccessModeRead, unit.TypePullRequests) |
|
}
|
|
|