diff options
author | David Svantesson <davidsvantesson@gmail.com> | 2019-12-04 02:08:56 +0100 |
---|---|---|
committer | techknowlogick <techknowlogick@gitea.io> | 2019-12-03 20:08:56 -0500 |
commit | bac4b78e0908c0cb01a3842436950c7bcf793cf9 (patch) | |
tree | a3c80aebb1ca69bf6e518b881229158dccf4ddd7 /models/branches.go | |
parent | 6460284085b0b416d61c57d729d47e932ac05efe (diff) | |
download | gitea-bac4b78e0908c0cb01a3842436950c7bcf793cf9.tar.gz gitea-bac4b78e0908c0cb01a3842436950c7bcf793cf9.zip |
Branch protection: Possibility to not use whitelist but allow anyone with write access (#9055)
* Possibility to not use whitelist but allow anyone with write access
* fix existing test
* rename migration function
* Try to give a better name for migration step
* Clear settings if higher level setting is not set
* Move official reviews to db instead of counting approvals each time
* migration
* fix
* fix migration
* fix migration
* Remove NOT NULL from EnableWhitelist as migration isn't possible
* Fix migration, reviews are connected to issues.
* Fix SQL query issues in GetReviewersByPullID.
* Simplify function GetReviewersByIssueID
* Handle reviewers that has been deleted
* Ensure reviews for test is in a well defined order
* Only clear and set official reviews when it is an approve or reject.
Diffstat (limited to 'models/branches.go')
-rw-r--r-- | models/branches.go | 82 |
1 files changed, 60 insertions, 22 deletions
diff --git a/models/branches.go b/models/branches.go index 46670b18a0..cf4b4fe393 100644 --- a/models/branches.go +++ b/models/branches.go @@ -39,6 +39,7 @@ type ProtectedBranch struct { MergeWhitelistTeamIDs []int64 `xorm:"JSON TEXT"` EnableStatusCheck bool `xorm:"NOT NULL DEFAULT false"` StatusCheckContexts []string `xorm:"JSON TEXT"` + EnableApprovalsWhitelist bool `xorm:"NOT NULL DEFAULT false"` ApprovalsWhitelistUserIDs []int64 `xorm:"JSON TEXT"` ApprovalsWhitelistTeamIDs []int64 `xorm:"JSON TEXT"` RequiredApprovals int64 `xorm:"NOT NULL DEFAULT 0"` @@ -53,10 +54,25 @@ func (protectBranch *ProtectedBranch) IsProtected() bool { // CanUserPush returns if some user could push to this protected branch func (protectBranch *ProtectedBranch) CanUserPush(userID int64) bool { - if !protectBranch.EnableWhitelist { + if !protectBranch.CanPush { return false } + if !protectBranch.EnableWhitelist { + if user, err := GetUserByID(userID); err != nil { + log.Error("GetUserByID: %v", err) + return false + } else if repo, err := GetRepositoryByID(protectBranch.RepoID); err != nil { + log.Error("GetRepositoryByID: %v", err) + return false + } else if writeAccess, err := HasAccessUnit(user, repo, UnitTypeCode, AccessModeWrite); err != nil { + log.Error("HasAccessUnit: %v", err) + return false + } else { + return writeAccess + } + } + if base.Int64sContains(protectBranch.WhitelistUserIDs, userID) { return true } @@ -95,6 +111,38 @@ func (protectBranch *ProtectedBranch) CanUserMerge(userID int64) bool { return in } +// IsUserOfficialReviewer check if user is official reviewer for the branch (counts towards required approvals) +func (protectBranch *ProtectedBranch) IsUserOfficialReviewer(user *User) (bool, error) { + return protectBranch.isUserOfficialReviewer(x, user) +} + +func (protectBranch *ProtectedBranch) isUserOfficialReviewer(e Engine, user *User) (bool, error) { + repo, err := getRepositoryByID(e, protectBranch.RepoID) + if err != nil { + return false, err + } + + if !protectBranch.EnableApprovalsWhitelist { + // Anyone with write access is considered official reviewer + writeAccess, err := hasAccessUnit(e, user, repo, UnitTypeCode, AccessModeWrite) + if err != nil { + return false, err + } + return writeAccess, nil + } + + if base.Int64sContains(protectBranch.ApprovalsWhitelistUserIDs, user.ID) { + return true, nil + } + + inTeam, err := isUserInTeams(e, user.ID, protectBranch.ApprovalsWhitelistTeamIDs) + if err != nil { + return false, err + } + + return inTeam, nil +} + // HasEnoughApprovals returns true if pr has enough granted approvals. func (protectBranch *ProtectedBranch) HasEnoughApprovals(pr *PullRequest) bool { if protectBranch.RequiredApprovals == 0 { @@ -105,30 +153,16 @@ func (protectBranch *ProtectedBranch) HasEnoughApprovals(pr *PullRequest) bool { // GetGrantedApprovalsCount returns the number of granted approvals for pr. A granted approval must be authored by a user in an approval whitelist. func (protectBranch *ProtectedBranch) GetGrantedApprovalsCount(pr *PullRequest) int64 { - reviews, err := GetReviewersByPullID(pr.IssueID) + approvals, err := x.Where("issue_id = ?", pr.Issue.ID). + And("type = ?", ReviewTypeApprove). + And("official = ?", true). + Count(new(Review)) if err != nil { - log.Error("GetReviewersByPullID: %v", err) + log.Error("GetGrantedApprovalsCount: %v", err) return 0 } - approvals := int64(0) - userIDs := make([]int64, 0) - for _, review := range reviews { - if review.Type != ReviewTypeApprove { - continue - } - if base.Int64sContains(protectBranch.ApprovalsWhitelistUserIDs, review.ID) { - approvals++ - continue - } - userIDs = append(userIDs, review.ID) - } - approvalTeamCount, err := UsersInTeamsCount(userIDs, protectBranch.ApprovalsWhitelistTeamIDs) - if err != nil { - log.Error("UsersInTeamsCount: %v", err) - return 0 - } - return approvalTeamCount + approvals + return approvals } // GetProtectedBranchByRepoID getting protected branch by repo ID @@ -139,8 +173,12 @@ func GetProtectedBranchByRepoID(repoID int64) ([]*ProtectedBranch, error) { // GetProtectedBranchBy getting protected branch by ID/Name func GetProtectedBranchBy(repoID int64, branchName string) (*ProtectedBranch, error) { + return getProtectedBranchBy(x, repoID, branchName) +} + +func getProtectedBranchBy(e Engine, repoID int64, branchName string) (*ProtectedBranch, error) { rel := &ProtectedBranch{RepoID: repoID, BranchName: branchName} - has, err := x.Get(rel) + has, err := e.Get(rel) if err != nil { return nil, err } |