Skip to content

Commit 91eedf7

Browse files
committed
Merge branch 'main' into lunny/fix_project_issues_list
2 parents a0a0324 + 1ba7cbb commit 91eedf7

File tree

15 files changed

+236
-61
lines changed

15 files changed

+236
-61
lines changed

models/asymkey/gpg_key_commit_verification.go

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"code.gitea.io/gitea/models/db"
1313
repo_model "code.gitea.io/gitea/models/repo"
1414
user_model "code.gitea.io/gitea/models/user"
15+
"code.gitea.io/gitea/modules/container"
1516
"code.gitea.io/gitea/modules/git"
1617
"code.gitea.io/gitea/modules/log"
1718
"code.gitea.io/gitea/modules/setting"
@@ -71,21 +72,41 @@ const (
7172
)
7273

7374
// ParseCommitsWithSignature checks if signaute of commits are corresponding to users gpg keys.
74-
func ParseCommitsWithSignature(ctx context.Context, oldCommits []*user_model.UserCommit, repoTrustModel repo_model.TrustModelType, isOwnerMemberCollaborator func(*user_model.User) (bool, error)) []*SignCommit {
75+
func ParseCommitsWithSignature(ctx context.Context, oldCommits []*user_model.UserCommit, repoTrustModel repo_model.TrustModelType, isOwnerMemberCollaborator func(*user_model.User) (bool, error)) ([]*SignCommit, error) {
7576
newCommits := make([]*SignCommit, 0, len(oldCommits))
7677
keyMap := map[string]bool{}
7778

79+
emails := make(container.Set[string])
7880
for _, c := range oldCommits {
81+
if c.Committer != nil {
82+
emails.Add(c.Committer.Email)
83+
}
84+
}
85+
86+
emailUsers, err := user_model.GetUsersByEmails(ctx, emails.Values())
87+
if err != nil {
88+
return nil, err
89+
}
90+
91+
for _, c := range oldCommits {
92+
committer, ok := emailUsers[c.Committer.Email]
93+
if !ok && c.Committer != nil {
94+
committer = &user_model.User{
95+
Name: c.Committer.Name,
96+
Email: c.Committer.Email,
97+
}
98+
}
99+
79100
signCommit := &SignCommit{
80101
UserCommit: c,
81-
Verification: ParseCommitWithSignature(ctx, c.Commit),
102+
Verification: parseCommitWithSignatureCommitter(ctx, c.Commit, committer),
82103
}
83104

84105
_ = CalculateTrustStatus(signCommit.Verification, repoTrustModel, isOwnerMemberCollaborator, &keyMap)
85106

86107
newCommits = append(newCommits, signCommit)
87108
}
88-
return newCommits
109+
return newCommits, nil
89110
}
90111

91112
// ParseCommitWithSignature check if signature is good against keystore.
@@ -113,6 +134,10 @@ func ParseCommitWithSignature(ctx context.Context, c *git.Commit) *CommitVerific
113134
}
114135
}
115136

137+
return parseCommitWithSignatureCommitter(ctx, c, committer)
138+
}
139+
140+
func parseCommitWithSignatureCommitter(ctx context.Context, c *git.Commit, committer *user_model.User) *CommitVerification {
116141
// If no signature just report the committer
117142
if c.Signature == nil {
118143
return &CommitVerification{

models/git/commit_status.go

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,7 @@ type SignCommitWithStatuses struct {
497497
}
498498

499499
// ParseCommitsWithStatus checks commits latest statuses and calculates its worst status state
500-
func ParseCommitsWithStatus(ctx context.Context, oldCommits []*asymkey_model.SignCommit, repo *repo_model.Repository) []*SignCommitWithStatuses {
500+
func ParseCommitsWithStatus(ctx context.Context, oldCommits []*asymkey_model.SignCommit, repo *repo_model.Repository) ([]*SignCommitWithStatuses, error) {
501501
newCommits := make([]*SignCommitWithStatuses, 0, len(oldCommits))
502502

503503
for _, c := range oldCommits {
@@ -506,15 +506,14 @@ func ParseCommitsWithStatus(ctx context.Context, oldCommits []*asymkey_model.Sig
506506
}
507507
statuses, _, err := GetLatestCommitStatus(ctx, repo.ID, commit.ID.String(), db.ListOptions{})
508508
if err != nil {
509-
log.Error("GetLatestCommitStatus: %v", err)
510-
} else {
511-
commit.Statuses = statuses
512-
commit.Status = CalcCommitStatus(statuses)
509+
return nil, err
513510
}
514511

512+
commit.Statuses = statuses
513+
commit.Status = CalcCommitStatus(statuses)
515514
newCommits = append(newCommits, commit)
516515
}
517-
return newCommits
516+
return newCommits, nil
518517
}
519518

520519
// hashCommitStatusContext hash context
@@ -523,18 +522,23 @@ func hashCommitStatusContext(context string) string {
523522
}
524523

525524
// ConvertFromGitCommit converts git commits into SignCommitWithStatuses
526-
func ConvertFromGitCommit(ctx context.Context, commits []*git.Commit, repo *repo_model.Repository) []*SignCommitWithStatuses {
527-
return ParseCommitsWithStatus(ctx,
528-
asymkey_model.ParseCommitsWithSignature(
529-
ctx,
530-
user_model.ValidateCommitsWithEmails(ctx, commits),
531-
repo.GetTrustModel(),
532-
func(user *user_model.User) (bool, error) {
533-
return repo_model.IsOwnerMemberCollaborator(ctx, repo, user.ID)
534-
},
535-
),
536-
repo,
525+
func ConvertFromGitCommit(ctx context.Context, commits []*git.Commit, repo *repo_model.Repository) ([]*SignCommitWithStatuses, error) {
526+
validatedCommits, err := user_model.ValidateCommitsWithEmails(ctx, commits)
527+
if err != nil {
528+
return nil, err
529+
}
530+
signedCommits, err := asymkey_model.ParseCommitsWithSignature(
531+
ctx,
532+
validatedCommits,
533+
repo.GetTrustModel(),
534+
func(user *user_model.User) (bool, error) {
535+
return repo_model.IsOwnerMemberCollaborator(ctx, repo, user.ID)
536+
},
537537
)
538+
if err != nil {
539+
return nil, err
540+
}
541+
return ParseCommitsWithStatus(ctx, signedCommits, repo)
538542
}
539543

540544
// CommitStatusesHideActionsURL hide Gitea Actions urls

models/issues/comment.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -802,7 +802,10 @@ func (c *Comment) LoadPushCommits(ctx context.Context) (err error) {
802802
}
803803
defer closer.Close()
804804

805-
c.Commits = git_model.ConvertFromGitCommit(ctx, gitRepo.GetCommitsFromIDs(data.CommitIDs), c.Issue.Repo)
805+
c.Commits, err = git_model.ConvertFromGitCommit(ctx, gitRepo.GetCommitsFromIDs(data.CommitIDs), c.Issue.Repo)
806+
if err != nil {
807+
return err
808+
}
806809
c.CommitsNum = int64(len(c.Commits))
807810
}
808811

models/issues/comment_code.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,10 @@ func findCodeComments(ctx context.Context, opts FindCommentsOptions, issue *Issu
8686
ids = append(ids, comment.ReviewID)
8787
}
8888
}
89-
if err := e.In("id", ids).Find(&reviews); err != nil {
90-
return nil, err
89+
if len(ids) > 0 {
90+
if err := e.In("id", ids).Find(&reviews); err != nil {
91+
return nil, err
92+
}
9193
}
9294

9395
n := 0

models/user/user.go

Lines changed: 68 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1129,28 +1129,85 @@ func ValidateCommitWithEmail(ctx context.Context, c *git.Commit) *User {
11291129
}
11301130

11311131
// ValidateCommitsWithEmails checks if authors' e-mails of commits are corresponding to users.
1132-
func ValidateCommitsWithEmails(ctx context.Context, oldCommits []*git.Commit) []*UserCommit {
1132+
func ValidateCommitsWithEmails(ctx context.Context, oldCommits []*git.Commit) ([]*UserCommit, error) {
11331133
var (
1134-
emails = make(map[string]*User)
11351134
newCommits = make([]*UserCommit, 0, len(oldCommits))
1135+
emailSet = make(container.Set[string])
11361136
)
11371137
for _, c := range oldCommits {
1138-
var u *User
11391138
if c.Author != nil {
1140-
if v, ok := emails[c.Author.Email]; !ok {
1141-
u, _ = GetUserByEmail(ctx, c.Author.Email)
1142-
emails[c.Author.Email] = u
1143-
} else {
1144-
u = v
1145-
}
1139+
emailSet.Add(c.Author.Email)
11461140
}
1141+
}
1142+
1143+
emailUserMap, err := GetUsersByEmails(ctx, emailSet.Values())
1144+
if err != nil {
1145+
return nil, err
1146+
}
11471147

1148+
for _, c := range oldCommits {
1149+
user, ok := emailUserMap[c.Author.Email]
1150+
if !ok {
1151+
user = &User{
1152+
Name: c.Author.Name,
1153+
Email: c.Author.Email,
1154+
}
1155+
}
11481156
newCommits = append(newCommits, &UserCommit{
1149-
User: u,
1157+
User: user,
11501158
Commit: c,
11511159
})
11521160
}
1153-
return newCommits
1161+
return newCommits, nil
1162+
}
1163+
1164+
func GetUsersByEmails(ctx context.Context, emails []string) (map[string]*User, error) {
1165+
if len(emails) == 0 {
1166+
return nil, nil
1167+
}
1168+
1169+
needCheckEmails := make(container.Set[string])
1170+
needCheckUserNames := make(container.Set[string])
1171+
for _, email := range emails {
1172+
if strings.HasSuffix(email, fmt.Sprintf("@%s", setting.Service.NoReplyAddress)) {
1173+
username := strings.TrimSuffix(email, fmt.Sprintf("@%s", setting.Service.NoReplyAddress))
1174+
needCheckUserNames.Add(username)
1175+
} else {
1176+
needCheckEmails.Add(strings.ToLower(email))
1177+
}
1178+
}
1179+
1180+
emailAddresses := make([]*EmailAddress, 0, len(needCheckEmails))
1181+
if err := db.GetEngine(ctx).In("lower_email", needCheckEmails.Values()).
1182+
And("is_activated=?", true).
1183+
Find(&emailAddresses); err != nil {
1184+
return nil, err
1185+
}
1186+
userIDs := make(container.Set[int64])
1187+
for _, email := range emailAddresses {
1188+
userIDs.Add(email.UID)
1189+
}
1190+
users, err := GetUsersByIDs(ctx, userIDs.Values())
1191+
if err != nil {
1192+
return nil, err
1193+
}
1194+
1195+
results := make(map[string]*User, len(emails))
1196+
for _, user := range users {
1197+
if user.KeepEmailPrivate {
1198+
results[user.LowerName+"@"+setting.Service.NoReplyAddress] = user
1199+
} else {
1200+
results[user.Email] = user
1201+
}
1202+
}
1203+
users = make([]*User, 0, len(needCheckUserNames))
1204+
if err := db.GetEngine(ctx).In("lower_name", needCheckUserNames.Values()).Find(&users); err != nil {
1205+
return nil, err
1206+
}
1207+
for _, user := range users {
1208+
results[user.LowerName+"@"+setting.Service.NoReplyAddress] = user
1209+
}
1210+
return results, nil
11541211
}
11551212

11561213
// GetUserByEmail returns the user object by given e-mail if exists.

routers/web/repo/blame.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,12 @@ func processBlameParts(ctx *context.Context, blameParts []*git.BlamePart) map[st
234234
}
235235

236236
// populate commit email addresses to later look up avatars.
237-
for _, c := range user_model.ValidateCommitsWithEmails(ctx, commits) {
237+
validatedCommits, err := user_model.ValidateCommitsWithEmails(ctx, commits)
238+
if err != nil {
239+
ctx.ServerError("ValidateCommitsWithEmails", err)
240+
return nil
241+
}
242+
for _, c := range validatedCommits {
238243
commitNames[c.ID.String()] = c
239244
}
240245

routers/web/repo/commit.go

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,11 @@ func Commits(ctx *context.Context) {
8080
ctx.ServerError("CommitsByRange", err)
8181
return
8282
}
83-
ctx.Data["Commits"] = processGitCommits(ctx, commits)
83+
ctx.Data["Commits"], err = processGitCommits(ctx, commits)
84+
if err != nil {
85+
ctx.ServerError("processGitCommits", err)
86+
return
87+
}
8488
commitIDs := make([]string, 0, len(commits))
8589
for _, c := range commits {
8690
commitIDs = append(commitIDs, c.ID.String())
@@ -192,7 +196,11 @@ func SearchCommits(ctx *context.Context) {
192196
return
193197
}
194198
ctx.Data["CommitCount"] = len(commits)
195-
ctx.Data["Commits"] = processGitCommits(ctx, commits)
199+
ctx.Data["Commits"], err = processGitCommits(ctx, commits)
200+
if err != nil {
201+
ctx.ServerError("processGitCommits", err)
202+
return
203+
}
196204

197205
ctx.Data["Keyword"] = query
198206
if all {
@@ -235,7 +243,11 @@ func FileHistory(ctx *context.Context) {
235243
ctx.ServerError("CommitsByFileAndRange", err)
236244
return
237245
}
238-
ctx.Data["Commits"] = processGitCommits(ctx, commits)
246+
ctx.Data["Commits"], err = processGitCommits(ctx, commits)
247+
if err != nil {
248+
ctx.ServerError("processGitCommits", err)
249+
return
250+
}
239251

240252
ctx.Data["Username"] = ctx.Repo.Owner.Name
241253
ctx.Data["Reponame"] = ctx.Repo.Repository.Name
@@ -416,13 +428,16 @@ func RawDiff(ctx *context.Context) {
416428
}
417429
}
418430

419-
func processGitCommits(ctx *context.Context, gitCommits []*git.Commit) []*git_model.SignCommitWithStatuses {
420-
commits := git_model.ConvertFromGitCommit(ctx, gitCommits, ctx.Repo.Repository)
431+
func processGitCommits(ctx *context.Context, gitCommits []*git.Commit) ([]*git_model.SignCommitWithStatuses, error) {
432+
commits, err := git_model.ConvertFromGitCommit(ctx, gitCommits, ctx.Repo.Repository)
433+
if err != nil {
434+
return nil, err
435+
}
421436
if !ctx.Repo.CanRead(unit_model.TypeActions) {
422437
for _, commit := range commits {
423438
commit.Status.HideActionsURL(ctx)
424439
git_model.CommitStatusesHideActionsURL(ctx, commit.Statuses)
425440
}
426441
}
427-
return commits
442+
return commits, nil
428443
}

routers/web/repo/compare.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -647,7 +647,11 @@ func PrepareCompareDiff(
647647
return false
648648
}
649649

650-
commits := processGitCommits(ctx, ci.CompareInfo.Commits)
650+
commits, err := processGitCommits(ctx, ci.CompareInfo.Commits)
651+
if err != nil {
652+
ctx.ServerError("processGitCommits", err)
653+
return false
654+
}
651655
ctx.Data["Commits"] = commits
652656
ctx.Data["CommitCount"] = len(commits)
653657

routers/web/repo/issue_page_meta.go

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -79,27 +79,35 @@ func retrieveRepoIssueMetaData(ctx *context.Context, repo *repo_model.Repository
7979
return data
8080
}
8181

82-
data.CanModifyIssueOrPull = ctx.Repo.CanWriteIssuesOrPulls(isPull) && !ctx.Repo.Repository.IsArchived
83-
if !data.CanModifyIssueOrPull {
82+
// it sets "Branches" template data,
83+
// it is used to render the "edit PR target branches" dropdown, and the "branch selector" in the issue's sidebar.
84+
PrepareBranchList(ctx)
85+
if ctx.Written() {
8486
return data
8587
}
8688

87-
data.retrieveAssigneesDataForIssueWriter(ctx)
89+
// it sets the "Assignees" template data, and the data is also used to "mention" users.
90+
data.retrieveAssigneesData(ctx)
8891
if ctx.Written() {
8992
return data
9093
}
9194

92-
data.retrieveMilestonesDataForIssueWriter(ctx)
93-
if ctx.Written() {
95+
// TODO: the issue/pull permissions are quite complex and unclear
96+
// A reader could create an issue/PR with setting some meta (eg: assignees from issue template, reviewers, target branch)
97+
// A reader(creator) could update some meta (eg: target branch), but can't change assignees anymore.
98+
// For non-creator users, only writers could update some meta (eg: assignees, milestone, project)
99+
// Need to clarify the logic and add some tests in the future
100+
data.CanModifyIssueOrPull = ctx.Repo.CanWriteIssuesOrPulls(isPull) && !ctx.Repo.Repository.IsArchived
101+
if !data.CanModifyIssueOrPull {
94102
return data
95103
}
96104

97-
data.retrieveProjectsDataForIssueWriter(ctx)
105+
data.retrieveMilestonesDataForIssueWriter(ctx)
98106
if ctx.Written() {
99107
return data
100108
}
101109

102-
PrepareBranchList(ctx)
110+
data.retrieveProjectsDataForIssueWriter(ctx)
103111
if ctx.Written() {
104112
return data
105113
}
@@ -131,7 +139,7 @@ func (d *IssuePageMetaData) retrieveMilestonesDataForIssueWriter(ctx *context.Co
131139
}
132140
}
133141

134-
func (d *IssuePageMetaData) retrieveAssigneesDataForIssueWriter(ctx *context.Context) {
142+
func (d *IssuePageMetaData) retrieveAssigneesData(ctx *context.Context) {
135143
var err error
136144
d.AssigneesData.CandidateAssignees, err = repo_model.GetRepoAssignees(ctx, d.Repository)
137145
if err != nil {

0 commit comments

Comments
 (0)