@@ -7,14 +7,7 @@ import (
77 "context"
88
99 issues_model "code.gitea.io/gitea/models/issues"
10- "code.gitea.io/gitea/models/organization"
11- org_model "code.gitea.io/gitea/models/organization"
12- "code.gitea.io/gitea/models/perm"
13- access_model "code.gitea.io/gitea/models/perm/access"
14- repo_model "code.gitea.io/gitea/models/repo"
15- "code.gitea.io/gitea/models/unit"
1610 user_model "code.gitea.io/gitea/models/user"
17- "code.gitea.io/gitea/modules/log"
1811 notify_service "code.gitea.io/gitea/services/notify"
1912)
2013
@@ -60,288 +53,3 @@ func ToggleAssigneeWithNotify(ctx context.Context, issue *issues_model.Issue, do
6053
6154 return removed , comment , err
6255}
63-
64- // ReviewRequest add or remove a review request from a user for this PR, and make comment for it.
65- func ReviewRequest (ctx context.Context , pr * issues_model.PullRequest , doer * user_model.User , permDoer * access_model.Permission , reviewer * user_model.User , isAdd bool ) (comment * issues_model.Comment , err error ) {
66- err = isValidReviewRequest (ctx , reviewer , doer , isAdd , pr .Issue , permDoer )
67- if err != nil {
68- return nil , err
69- }
70-
71- if isAdd {
72- comment , err = issues_model .AddReviewRequest (ctx , pr .Issue , reviewer , doer )
73- } else {
74- comment , err = issues_model .RemoveReviewRequest (ctx , pr .Issue , reviewer , doer )
75- }
76-
77- if err != nil {
78- return nil , err
79- }
80-
81- if comment != nil {
82- notify_service .PullRequestReviewRequest (ctx , doer , pr .Issue , reviewer , isAdd , comment )
83- }
84-
85- return comment , err
86- }
87-
88- func ReviewRequests (ctx context.Context , pr * issues_model.PullRequest , doer * user_model.User , reviewers []* user_model.User , reviewTeams []* org_model.Team ) (comments []* issues_model.Comment , err error ) {
89- for _ , reviewer := range reviewers {
90- comment , err := ReviewRequest (ctx , pr , doer , nil , reviewer , true )
91- if err != nil {
92- return nil , err
93- }
94- comments = append (comments , comment )
95- }
96-
97- for _ , reviewTeam := range reviewTeams {
98- comment , err := TeamReviewRequest (ctx , pr , doer , reviewTeam , true )
99- if err != nil {
100- return nil , err
101- }
102- comments = append (comments , comment )
103- }
104-
105- return comments , nil
106- }
107-
108- // isValidReviewRequest Check permission for ReviewRequest
109- func isValidReviewRequest (ctx context.Context , reviewer , doer * user_model.User , isAdd bool , issue * issues_model.Issue , permDoer * access_model.Permission ) error {
110- if reviewer .IsOrganization () {
111- return issues_model.ErrNotValidReviewRequest {
112- Reason : "Organization can't be added as reviewer" ,
113- UserID : doer .ID ,
114- RepoID : issue .Repo .ID ,
115- }
116- }
117- if doer .IsOrganization () {
118- return issues_model.ErrNotValidReviewRequest {
119- Reason : "Organization can't be doer to add reviewer" ,
120- UserID : doer .ID ,
121- RepoID : issue .Repo .ID ,
122- }
123- }
124-
125- permReviewer , err := access_model .GetUserRepoPermission (ctx , issue .Repo , reviewer )
126- if err != nil {
127- return err
128- }
129-
130- if permDoer == nil {
131- permDoer = new (access_model.Permission )
132- * permDoer , err = access_model .GetUserRepoPermission (ctx , issue .Repo , doer )
133- if err != nil {
134- return err
135- }
136- }
137-
138- lastReview , err := issues_model .GetReviewByIssueIDAndUserID (ctx , issue .ID , reviewer .ID )
139- if err != nil && ! issues_model .IsErrReviewNotExist (err ) {
140- return err
141- }
142-
143- canDoerChangeReviewRequests := CanDoerChangeReviewRequests (ctx , doer , issue .Repo , issue .PosterID )
144-
145- if isAdd {
146- if ! permReviewer .CanAccessAny (perm .AccessModeRead , unit .TypePullRequests ) {
147- return issues_model.ErrNotValidReviewRequest {
148- Reason : "Reviewer can't read" ,
149- UserID : doer .ID ,
150- RepoID : issue .Repo .ID ,
151- }
152- }
153-
154- if reviewer .ID == issue .PosterID && issue .OriginalAuthorID == 0 {
155- return issues_model.ErrNotValidReviewRequest {
156- Reason : "poster of pr can't be reviewer" ,
157- UserID : doer .ID ,
158- RepoID : issue .Repo .ID ,
159- }
160- }
161-
162- if canDoerChangeReviewRequests {
163- return nil
164- }
165-
166- if doer .ID == issue .PosterID && issue .OriginalAuthorID == 0 && lastReview != nil && lastReview .Type != issues_model .ReviewTypeRequest {
167- return nil
168- }
169-
170- return issues_model.ErrNotValidReviewRequest {
171- Reason : "Doer can't choose reviewer" ,
172- UserID : doer .ID ,
173- RepoID : issue .Repo .ID ,
174- }
175- }
176-
177- if canDoerChangeReviewRequests {
178- return nil
179- }
180-
181- if lastReview != nil && lastReview .Type == issues_model .ReviewTypeRequest && lastReview .ReviewerID == doer .ID {
182- return nil
183- }
184-
185- return issues_model.ErrNotValidReviewRequest {
186- Reason : "Doer can't remove reviewer" ,
187- UserID : doer .ID ,
188- RepoID : issue .Repo .ID ,
189- }
190- }
191-
192- // isValidTeamReviewRequest Check permission for ReviewRequest Team
193- func isValidTeamReviewRequest (ctx context.Context , reviewer * organization.Team , doer * user_model.User , isAdd bool , issue * issues_model.Issue ) error {
194- if doer .IsOrganization () {
195- return issues_model.ErrNotValidReviewRequest {
196- Reason : "Organization can't be doer to add reviewer" ,
197- UserID : doer .ID ,
198- RepoID : issue .Repo .ID ,
199- }
200- }
201-
202- canDoerChangeReviewRequests := CanDoerChangeReviewRequests (ctx , doer , issue .Repo , issue .PosterID )
203-
204- if isAdd {
205- if issue .Repo .IsPrivate {
206- hasTeam := organization .HasTeamRepo (ctx , reviewer .OrgID , reviewer .ID , issue .RepoID )
207-
208- if ! hasTeam {
209- return issues_model.ErrNotValidReviewRequest {
210- Reason : "Reviewing team can't read repo" ,
211- UserID : doer .ID ,
212- RepoID : issue .Repo .ID ,
213- }
214- }
215- }
216-
217- if canDoerChangeReviewRequests {
218- return nil
219- }
220-
221- return issues_model.ErrNotValidReviewRequest {
222- Reason : "Doer can't choose reviewer" ,
223- UserID : doer .ID ,
224- RepoID : issue .Repo .ID ,
225- }
226- }
227-
228- if canDoerChangeReviewRequests {
229- return nil
230- }
231-
232- return issues_model.ErrNotValidReviewRequest {
233- Reason : "Doer can't remove reviewer" ,
234- UserID : doer .ID ,
235- RepoID : issue .Repo .ID ,
236- }
237- }
238-
239- // TeamReviewRequest add or remove a review request from a team for this PR, and make comment for it.
240- func TeamReviewRequest (ctx context.Context , pr * issues_model.PullRequest , doer * user_model.User , reviewer * organization.Team , isAdd bool ) (comment * issues_model.Comment , err error ) {
241- err = isValidTeamReviewRequest (ctx , reviewer , doer , isAdd , pr .Issue )
242- if err != nil {
243- return nil , err
244- }
245- if isAdd {
246- comment , err = issues_model .AddTeamReviewRequest (ctx , pr .Issue , reviewer , doer )
247- } else {
248- comment , err = issues_model .RemoveTeamReviewRequest (ctx , pr .Issue , reviewer , doer )
249- }
250-
251- if err != nil {
252- return nil , err
253- }
254-
255- if comment == nil || ! isAdd {
256- return nil , nil
257- }
258-
259- return comment , teamReviewRequestNotify (ctx , pr .Issue , doer , reviewer , isAdd , comment )
260- }
261-
262- func ReviewRequestNotify (ctx context.Context , issue * issues_model.Issue , doer * user_model.User , reviewNotifiers []* ReviewRequestNotifier ) {
263- for _ , reviewNotifier := range reviewNotifiers {
264- if reviewNotifier .Reviewer != nil {
265- notify_service .PullRequestReviewRequest (ctx , issue .Poster , issue , reviewNotifier .Reviewer , reviewNotifier .IsAdd , reviewNotifier .Comment )
266- } else if reviewNotifier .ReviewTeam != nil {
267- if err := teamReviewRequestNotify (ctx , issue , issue .Poster , reviewNotifier .ReviewTeam , reviewNotifier .IsAdd , reviewNotifier .Comment ); err != nil {
268- log .Error ("teamReviewRequestNotify: %v" , err )
269- }
270- }
271- }
272- }
273-
274- // teamReviewRequestNotify notify all user in this team
275- func teamReviewRequestNotify (ctx context.Context , issue * issues_model.Issue , doer * user_model.User , reviewer * organization.Team , isAdd bool , comment * issues_model.Comment ) error {
276- // notify all user in this team
277- if err := comment .LoadIssue (ctx ); err != nil {
278- return err
279- }
280-
281- members , err := organization .GetTeamMembers (ctx , & organization.SearchMembersOptions {
282- TeamID : reviewer .ID ,
283- })
284- if err != nil {
285- return err
286- }
287-
288- for _ , member := range members {
289- if member .ID == comment .Issue .PosterID {
290- continue
291- }
292- comment .AssigneeID = member .ID
293- notify_service .PullRequestReviewRequest (ctx , doer , issue , member , isAdd , comment )
294- }
295-
296- return err
297- }
298-
299- // CanDoerChangeReviewRequests returns if the doer can add/remove review requests of a PR
300- func CanDoerChangeReviewRequests (ctx context.Context , doer * user_model.User , repo * repo_model.Repository , posterID int64 ) bool {
301- if repo .IsArchived {
302- return false
303- }
304- // The poster of the PR can change the reviewers
305- if doer .ID == posterID {
306- return true
307- }
308-
309- // The owner of the repo can change the reviewers
310- if doer .ID == repo .OwnerID {
311- return true
312- }
313-
314- // Collaborators of the repo can change the reviewers
315- isCollaborator , err := repo_model .IsCollaborator (ctx , repo .ID , doer .ID )
316- if err != nil {
317- log .Error ("IsCollaborator: %v" , err )
318- return false
319- }
320- if isCollaborator {
321- return true
322- }
323-
324- // If the repo's owner is an organization, members of teams with read permission on pull requests can change reviewers
325- if repo .Owner .IsOrganization () {
326- teams , err := organization .GetTeamsWithAccessToRepo (ctx , repo .OwnerID , repo .ID , perm .AccessModeRead )
327- if err != nil {
328- log .Error ("GetTeamsWithAccessToRepo: %v" , err )
329- return false
330- }
331- for _ , team := range teams {
332- if ! team .UnitEnabled (ctx , unit .TypePullRequests ) {
333- continue
334- }
335- isMember , err := organization .IsTeamMember (ctx , repo .OwnerID , team .ID , doer .ID )
336- if err != nil {
337- log .Error ("IsTeamMember: %v" , err )
338- continue
339- }
340- if isMember {
341- return true
342- }
343- }
344- }
345-
346- return false
347- }
0 commit comments