mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 09:31:53 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			90 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			90 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // 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)
 | |
| }
 |