summaryrefslogtreecommitdiffstats
path: root/models/branches.go
diff options
context:
space:
mode:
authorDavid Svantesson <davidsvantesson@gmail.com>2019-12-04 02:08:56 +0100
committertechknowlogick <techknowlogick@gitea.io>2019-12-03 20:08:56 -0500
commitbac4b78e0908c0cb01a3842436950c7bcf793cf9 (patch)
treea3c80aebb1ca69bf6e518b881229158dccf4ddd7 /models/branches.go
parent6460284085b0b416d61c57d729d47e932ac05efe (diff)
downloadgitea-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.go82
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
}