mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-04 01:34:27 +00:00 
			
		
		
		
	Fix access issues on milestone and issue overview pages. (#9603)
* Fix access issues on milestone and issue overview pages. * Fix filter algorithm
This commit is contained in:
		
				
					committed by
					
						
						techknowlogick
					
				
			
			
				
	
			
			
			
						parent
						
							8b24073713
						
					
				
				
					commit
					03d59bcd1d
				
			@@ -369,3 +369,23 @@ func hasAccess(e Engine, userID int64, repo *Repository) (bool, error) {
 | 
			
		||||
func HasAccess(userID int64, repo *Repository) (bool, error) {
 | 
			
		||||
	return hasAccess(x, userID, repo)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FilterOutRepoIdsWithoutUnitAccess filter out repos where user has no access to repositories
 | 
			
		||||
func FilterOutRepoIdsWithoutUnitAccess(u *User, repoIDs []int64, units ...UnitType) ([]int64, error) {
 | 
			
		||||
	i := 0
 | 
			
		||||
	for _, rID := range repoIDs {
 | 
			
		||||
		repo, err := GetRepositoryByID(rID)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		perm, err := GetUserRepoPermission(repo, u)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		if perm.CanReadAny(units...) {
 | 
			
		||||
			repoIDs[i] = rID
 | 
			
		||||
			i++
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return repoIDs[:i], nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -638,19 +638,20 @@ func (u *User) GetRepositoryIDs(units ...UnitType) ([]int64, error) {
 | 
			
		||||
func (u *User) GetOrgRepositoryIDs(units ...UnitType) ([]int64, error) {
 | 
			
		||||
	var ids []int64
 | 
			
		||||
 | 
			
		||||
	sess := x.Table("repository").
 | 
			
		||||
	if err := x.Table("repository").
 | 
			
		||||
		Cols("repository.id").
 | 
			
		||||
		Join("INNER", "team_user", "repository.owner_id = team_user.org_id").
 | 
			
		||||
		Join("INNER", "team_repo", "repository.is_private != ? OR (team_user.team_id = team_repo.team_id AND repository.id = team_repo.repo_id)", true)
 | 
			
		||||
 | 
			
		||||
	if len(units) > 0 {
 | 
			
		||||
		sess = sess.Join("INNER", "team_unit", "team_unit.team_id = team_user.team_id")
 | 
			
		||||
		sess = sess.In("team_unit.type", units)
 | 
			
		||||
		Join("INNER", "team_repo", "repository.is_private != ? OR (team_user.team_id = team_repo.team_id AND repository.id = team_repo.repo_id)", true).
 | 
			
		||||
		Where("team_user.uid = ?", u.ID).
 | 
			
		||||
		GroupBy("repository.id").Find(&ids); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ids, sess.
 | 
			
		||||
		Where("team_user.uid = ?", u.ID).
 | 
			
		||||
		GroupBy("repository.id").Find(&ids)
 | 
			
		||||
	if len(units) > 0 {
 | 
			
		||||
		return FilterOutRepoIdsWithoutUnitAccess(u, ids, units...)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ids, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetAccessRepoIDs returns all repositories IDs where user's or user is a team member organizations
 | 
			
		||||
 
 | 
			
		||||
@@ -188,9 +188,13 @@ func Milestones(ctx *context.Context) {
 | 
			
		||||
			ctx.ServerError("env.RepoIDs", err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		userRepoIDs, err = models.FilterOutRepoIdsWithoutUnitAccess(ctx.User, userRepoIDs, models.UnitTypeIssues, models.UnitTypePullRequests)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			ctx.ServerError("FilterOutRepoIdsWithoutUnitAccess", err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		unitType := models.UnitTypeIssues
 | 
			
		||||
		userRepoIDs, err = ctxUser.GetAccessRepoIDs(unitType)
 | 
			
		||||
		userRepoIDs, err = ctxUser.GetAccessRepoIDs(models.UnitTypeIssues, models.UnitTypePullRequests)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			ctx.ServerError("ctxUser.GetAccessRepoIDs", err)
 | 
			
		||||
			return
 | 
			
		||||
@@ -201,27 +205,30 @@ func Milestones(ctx *context.Context) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var repoIDs []int64
 | 
			
		||||
	if issueReposQueryPattern.MatchString(reposQuery) {
 | 
			
		||||
		// remove "[" and "]" from string
 | 
			
		||||
		reposQuery = reposQuery[1 : len(reposQuery)-1]
 | 
			
		||||
		//for each ID (delimiter ",") add to int to repoIDs
 | 
			
		||||
		reposSet := false
 | 
			
		||||
		for _, rID := range strings.Split(reposQuery, ",") {
 | 
			
		||||
			// Ensure nonempty string entries
 | 
			
		||||
			if rID != "" && rID != "0" {
 | 
			
		||||
				reposSet = true
 | 
			
		||||
				rIDint64, err := strconv.ParseInt(rID, 10, 64)
 | 
			
		||||
				if err == nil && com.IsSliceContainsInt64(userRepoIDs, rIDint64) {
 | 
			
		||||
					repoIDs = append(repoIDs, rIDint64)
 | 
			
		||||
	if len(reposQuery) != 0 {
 | 
			
		||||
		if issueReposQueryPattern.MatchString(reposQuery) {
 | 
			
		||||
			// remove "[" and "]" from string
 | 
			
		||||
			reposQuery = reposQuery[1 : len(reposQuery)-1]
 | 
			
		||||
			//for each ID (delimiter ",") add to int to repoIDs
 | 
			
		||||
			reposSet := false
 | 
			
		||||
			for _, rID := range strings.Split(reposQuery, ",") {
 | 
			
		||||
				// Ensure nonempty string entries
 | 
			
		||||
				if rID != "" && rID != "0" {
 | 
			
		||||
					reposSet = true
 | 
			
		||||
					rIDint64, err := strconv.ParseInt(rID, 10, 64)
 | 
			
		||||
					// If the repo id specified by query is not parseable or not accessible by user, just ignore it.
 | 
			
		||||
					if err == nil && com.IsSliceContainsInt64(userRepoIDs, rIDint64) {
 | 
			
		||||
						repoIDs = append(repoIDs, rIDint64)
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if reposSet && len(repoIDs) == 0 {
 | 
			
		||||
				// force an empty result
 | 
			
		||||
				repoIDs = []int64{-1}
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			log.Warn("issueReposQueryPattern not match with query")
 | 
			
		||||
		}
 | 
			
		||||
		if reposSet && len(repoIDs) == 0 {
 | 
			
		||||
			// force an empty result
 | 
			
		||||
			repoIDs = []int64{-1}
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		log.Error("issueReposQueryPattern not match with query")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(repoIDs) == 0 {
 | 
			
		||||
@@ -256,26 +263,6 @@ func Milestones(ctx *context.Context) {
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		showReposMap[rID] = repo
 | 
			
		||||
 | 
			
		||||
		// Check if user has access to given repository.
 | 
			
		||||
		perm, err := models.GetUserRepoPermission(repo, ctxUser)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			ctx.ServerError("GetUserRepoPermission", fmt.Errorf("[%d]%v", rID, err))
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if !perm.CanRead(models.UnitTypeIssues) {
 | 
			
		||||
			if log.IsTrace() {
 | 
			
		||||
				log.Trace("Permission Denied: User %-v cannot read %-v of repo %-v\n"+
 | 
			
		||||
					"User in repo has Permissions: %-+v",
 | 
			
		||||
					ctxUser,
 | 
			
		||||
					models.UnitTypeIssues,
 | 
			
		||||
					repo,
 | 
			
		||||
					perm)
 | 
			
		||||
			}
 | 
			
		||||
			ctx.Status(404)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	showRepos := models.RepositoryListOfMap(showReposMap)
 | 
			
		||||
@@ -345,9 +332,11 @@ var issueReposQueryPattern = regexp.MustCompile(`^\[\d+(,\d+)*,?\]$`)
 | 
			
		||||
// Issues render the user issues page
 | 
			
		||||
func Issues(ctx *context.Context) {
 | 
			
		||||
	isPullList := ctx.Params(":type") == "pulls"
 | 
			
		||||
	unitType := models.UnitTypeIssues
 | 
			
		||||
	if isPullList {
 | 
			
		||||
		ctx.Data["Title"] = ctx.Tr("pull_requests")
 | 
			
		||||
		ctx.Data["PageIsPulls"] = true
 | 
			
		||||
		unitType = models.UnitTypePullRequests
 | 
			
		||||
	} else {
 | 
			
		||||
		ctx.Data["Title"] = ctx.Tr("issues")
 | 
			
		||||
		ctx.Data["PageIsIssues"] = true
 | 
			
		||||
@@ -404,7 +393,7 @@ func Issues(ctx *context.Context) {
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			log.Error("issueReposQueryPattern not match with query")
 | 
			
		||||
			log.Warn("issueReposQueryPattern not match with query")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -424,11 +413,12 @@ func Issues(ctx *context.Context) {
 | 
			
		||||
			ctx.ServerError("env.RepoIDs", err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		unitType := models.UnitTypeIssues
 | 
			
		||||
		if isPullList {
 | 
			
		||||
			unitType = models.UnitTypePullRequests
 | 
			
		||||
		userRepoIDs, err = models.FilterOutRepoIdsWithoutUnitAccess(ctx.User, userRepoIDs, unitType)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			ctx.ServerError("FilterOutRepoIdsWithoutUnitAccess", err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		userRepoIDs, err = ctxUser.GetAccessRepoIDs(unitType)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			ctx.ServerError("ctxUser.GetAccessRepoIDs", err)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user