@@ -8,6 +8,12 @@ import (
8
8
"fmt"
9
9
"strings"
10
10
"time"
11
+
12
+ "code.gitea.io/gitea/modules/base"
13
+ "code.gitea.io/gitea/modules/log"
14
+ "code.gitea.io/gitea/modules/util"
15
+
16
+ "github.com/Unknwon/com"
11
17
)
12
18
13
19
const (
@@ -17,14 +23,43 @@ const (
17
23
18
24
// ProtectedBranch struct
19
25
type ProtectedBranch struct {
20
- ID int64 `xorm:"pk autoincr"`
21
- RepoID int64 `xorm:"UNIQUE(s)"`
22
- BranchName string `xorm:"UNIQUE(s)"`
23
- CanPush bool
24
- Created time.Time `xorm:"-"`
25
- CreatedUnix int64 `xorm:"created"`
26
- Updated time.Time `xorm:"-"`
27
- UpdatedUnix int64 `xorm:"updated"`
26
+ ID int64 `xorm:"pk autoincr"`
27
+ RepoID int64 `xorm:"UNIQUE(s)"`
28
+ BranchName string `xorm:"UNIQUE(s)"`
29
+ EnableWhitelist bool
30
+ WhitelistUserIDs []int64 `xorm:"JSON TEXT"`
31
+ WhitelistTeamIDs []int64 `xorm:"JSON TEXT"`
32
+ Created time.Time `xorm:"-"`
33
+ CreatedUnix int64 `xorm:"created"`
34
+ Updated time.Time `xorm:"-"`
35
+ UpdatedUnix int64 `xorm:"updated"`
36
+ }
37
+
38
+ // IsProtected returns if the branch is protected
39
+ func (protectBranch * ProtectedBranch ) IsProtected () bool {
40
+ return protectBranch .ID > 0
41
+ }
42
+
43
+ // CanUserPush returns if some user could push to this protected branch
44
+ func (protectBranch * ProtectedBranch ) CanUserPush (userID int64 ) bool {
45
+ if ! protectBranch .EnableWhitelist {
46
+ return false
47
+ }
48
+
49
+ if base .Int64sContains (protectBranch .WhitelistUserIDs , userID ) {
50
+ return true
51
+ }
52
+
53
+ if len (protectBranch .WhitelistTeamIDs ) == 0 {
54
+ return false
55
+ }
56
+
57
+ in , err := IsUserInTeams (userID , protectBranch .WhitelistTeamIDs )
58
+ if err != nil {
59
+ log .Error (1 , "IsUserInTeams:" , err )
60
+ return false
61
+ }
62
+ return in
28
63
}
29
64
30
65
// GetProtectedBranchByRepoID getting protected branch by repo ID
@@ -46,14 +81,81 @@ func GetProtectedBranchBy(repoID int64, BranchName string) (*ProtectedBranch, er
46
81
return rel , nil
47
82
}
48
83
84
+ // GetProtectedBranchByID getting protected branch by ID
85
+ func GetProtectedBranchByID (id int64 ) (* ProtectedBranch , error ) {
86
+ rel := & ProtectedBranch {ID : id }
87
+ has , err := x .Get (rel )
88
+ if err != nil {
89
+ return nil , err
90
+ }
91
+ if ! has {
92
+ return nil , nil
93
+ }
94
+ return rel , nil
95
+ }
96
+
97
+ // UpdateProtectBranch saves branch protection options of repository.
98
+ // If ID is 0, it creates a new record. Otherwise, updates existing record.
99
+ // This function also performs check if whitelist user and team's IDs have been changed
100
+ // to avoid unnecessary whitelist delete and regenerate.
101
+ func UpdateProtectBranch (repo * Repository , protectBranch * ProtectedBranch , whitelistUserIDs , whitelistTeamIDs []int64 ) (err error ) {
102
+ if err = repo .GetOwner (); err != nil {
103
+ return fmt .Errorf ("GetOwner: %v" , err )
104
+ }
105
+
106
+ hasUsersChanged := ! util .IsSliceInt64Eq (protectBranch .WhitelistUserIDs , whitelistUserIDs )
107
+ if hasUsersChanged {
108
+ protectBranch .WhitelistUserIDs = make ([]int64 , 0 , len (whitelistUserIDs ))
109
+ for _ , userID := range whitelistUserIDs {
110
+ has , err := hasAccess (x , userID , repo , AccessModeWrite )
111
+ if err != nil {
112
+ return fmt .Errorf ("HasAccess [user_id: %d, repo_id: %d]: %v" , userID , protectBranch .RepoID , err )
113
+ } else if ! has {
114
+ continue // Drop invalid user ID
115
+ }
116
+
117
+ protectBranch .WhitelistUserIDs = append (protectBranch .WhitelistUserIDs , userID )
118
+ }
119
+ }
120
+
121
+ // if the repo is in an orgniziation
122
+ hasTeamsChanged := ! util .IsSliceInt64Eq (protectBranch .WhitelistTeamIDs , whitelistTeamIDs )
123
+ if hasTeamsChanged {
124
+ teams , err := GetTeamsWithAccessToRepo (repo .OwnerID , repo .ID , AccessModeWrite )
125
+ if err != nil {
126
+ return fmt .Errorf ("GetTeamsWithAccessToRepo [org_id: %d, repo_id: %d]: %v" , repo .OwnerID , repo .ID , err )
127
+ }
128
+ protectBranch .WhitelistTeamIDs = make ([]int64 , 0 , len (teams ))
129
+ for i := range teams {
130
+ if teams [i ].HasWriteAccess () && com .IsSliceContainsInt64 (whitelistTeamIDs , teams [i ].ID ) {
131
+ protectBranch .WhitelistTeamIDs = append (protectBranch .WhitelistTeamIDs , teams [i ].ID )
132
+ }
133
+ }
134
+ }
135
+
136
+ // Make sure protectBranch.ID is not 0 for whitelists
137
+ if protectBranch .ID == 0 {
138
+ if _ , err = x .Insert (protectBranch ); err != nil {
139
+ return fmt .Errorf ("Insert: %v" , err )
140
+ }
141
+ return nil
142
+ }
143
+
144
+ if _ , err = x .Id (protectBranch .ID ).AllCols ().Update (protectBranch ); err != nil {
145
+ return fmt .Errorf ("Update: %v" , err )
146
+ }
147
+
148
+ return nil
149
+ }
150
+
49
151
// GetProtectedBranches get all protected branches
50
152
func (repo * Repository ) GetProtectedBranches () ([]* ProtectedBranch , error ) {
51
153
protectedBranches := make ([]* ProtectedBranch , 0 )
52
154
return protectedBranches , x .Find (& protectedBranches , & ProtectedBranch {RepoID : repo .ID })
53
155
}
54
156
55
157
// IsProtectedBranch checks if branch is protected
56
- func (repo * Repository ) IsProtectedBranch (branchName string ) (bool , error ) {
158
+ func (repo * Repository ) IsProtectedBranch (branchName string , doer * User ) (bool , error ) {
57
159
protectedBranch := & ProtectedBranch {
58
160
RepoID : repo .ID ,
59
161
BranchName : branchName ,
@@ -63,70 +165,12 @@ func (repo *Repository) IsProtectedBranch(branchName string) (bool, error) {
63
165
if err != nil {
64
166
return true , err
65
167
} else if has {
66
- return true , nil
168
+ return ! protectedBranch . CanUserPush ( doer . ID ) , nil
67
169
}
68
170
69
171
return false , nil
70
172
}
71
173
72
- // AddProtectedBranch add protection to branch
73
- func (repo * Repository ) AddProtectedBranch (branchName string , canPush bool ) error {
74
- protectedBranch := & ProtectedBranch {
75
- RepoID : repo .ID ,
76
- BranchName : branchName ,
77
- }
78
-
79
- has , err := x .Get (protectedBranch )
80
- if err != nil {
81
- return err
82
- } else if has {
83
- return nil
84
- }
85
-
86
- sess := x .NewSession ()
87
- defer sess .Close ()
88
- if err = sess .Begin (); err != nil {
89
- return err
90
- }
91
- protectedBranch .CanPush = canPush
92
- if _ , err = sess .InsertOne (protectedBranch ); err != nil {
93
- return err
94
- }
95
-
96
- return sess .Commit ()
97
- }
98
-
99
- // ChangeProtectedBranch access mode sets new access mode for the ProtectedBranch.
100
- func (repo * Repository ) ChangeProtectedBranch (id int64 , canPush bool ) error {
101
- ProtectedBranch := & ProtectedBranch {
102
- RepoID : repo .ID ,
103
- ID : id ,
104
- }
105
- has , err := x .Get (ProtectedBranch )
106
- if err != nil {
107
- return fmt .Errorf ("get ProtectedBranch: %v" , err )
108
- } else if ! has {
109
- return nil
110
- }
111
-
112
- if ProtectedBranch .CanPush == canPush {
113
- return nil
114
- }
115
- ProtectedBranch .CanPush = canPush
116
-
117
- sess := x .NewSession ()
118
- defer sess .Close ()
119
- if err = sess .Begin (); err != nil {
120
- return err
121
- }
122
-
123
- if _ , err = sess .Id (ProtectedBranch .ID ).AllCols ().Update (ProtectedBranch ); err != nil {
124
- return fmt .Errorf ("update ProtectedBranch: %v" , err )
125
- }
126
-
127
- return sess .Commit ()
128
- }
129
-
130
174
// DeleteProtectedBranch removes ProtectedBranch relation between the user and repository.
131
175
func (repo * Repository ) DeleteProtectedBranch (id int64 ) (err error ) {
132
176
protectedBranch := & ProtectedBranch {
@@ -148,15 +192,3 @@ func (repo *Repository) DeleteProtectedBranch(id int64) (err error) {
148
192
149
193
return sess .Commit ()
150
194
}
151
-
152
- // newProtectedBranch insert one queue
153
- func newProtectedBranch (protectedBranch * ProtectedBranch ) error {
154
- _ , err := x .InsertOne (protectedBranch )
155
- return err
156
- }
157
-
158
- // UpdateProtectedBranch update queue
159
- func UpdateProtectedBranch (protectedBranch * ProtectedBranch ) error {
160
- _ , err := x .Update (protectedBranch )
161
- return err
162
- }
0 commit comments