Skip to content

Commit 094176e

Browse files
committed
Cache gpg keys fetch from database when list commits
1 parent 4d23231 commit 094176e

File tree

9 files changed

+65
-42
lines changed

9 files changed

+65
-42
lines changed

routers/private/hook_verification.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"io"
1111
"os"
1212

13+
asymkey_model "code.gitea.io/gitea/models/asymkey"
1314
"code.gitea.io/gitea/modules/git"
1415
"code.gitea.io/gitea/modules/log"
1516
asymkey_service "code.gitea.io/gitea/services/asymkey"
@@ -84,6 +85,7 @@ func readAndVerifyCommit(sha string, repo *git.Repository, env []string) error {
8485
}()
8586

8687
commitID := git.MustIDFromString(sha)
88+
keysCache := make(map[string][]*asymkey_model.GPGKey)
8789

8890
return git.NewCommand("cat-file", "commit").AddDynamicArguments(sha).
8991
Run(repo.Ctx, &git.RunOpts{
@@ -96,7 +98,7 @@ func readAndVerifyCommit(sha string, repo *git.Repository, env []string) error {
9698
if err != nil {
9799
return err
98100
}
99-
verification := asymkey_service.ParseCommitWithSignature(ctx, commit)
101+
verification := asymkey_service.ParseCommitWithSignature(ctx, commit, keysCache)
100102
if !verification.Verified {
101103
cancel()
102104
return &errUnverifiedCommit{

routers/web/repo/commit.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,8 @@ func Diff(ctx *context.Context) {
384384
ctx.Data["CommitStatus"] = git_model.CalcCommitStatus(statuses)
385385
ctx.Data["CommitStatuses"] = statuses
386386

387-
verification := asymkey_service.ParseCommitWithSignature(ctx, commit)
387+
keysCache := make(map[string][]*asymkey_model.GPGKey)
388+
verification := asymkey_service.ParseCommitWithSignature(ctx, commit, keysCache)
388389
ctx.Data["Verification"] = verification
389390
ctx.Data["Author"] = user_model.ValidateCommitWithEmail(ctx, commit)
390391
ctx.Data["Parents"] = parents

routers/web/repo/view.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,8 @@ func loadLatestCommitData(ctx *context.Context, latestCommit *git.Commit) bool {
119119
// or of directory if not in root directory.
120120
ctx.Data["LatestCommit"] = latestCommit
121121
if latestCommit != nil {
122-
verification := asymkey_service.ParseCommitWithSignature(ctx, latestCommit)
122+
keysCache := make(map[string][]*asymkey_model.GPGKey)
123+
verification := asymkey_service.ParseCommitWithSignature(ctx, latestCommit, keysCache)
123124

124125
if err := asymkey_model.CalculateTrustStatus(verification, ctx.Repo.Repository.GetTrustModel(), func(user *user_model.User) (bool, error) {
125126
return repo_model.IsOwnerMemberCollaborator(ctx, ctx.Repo.Repository, user.ID)

services/asymkey/commit.go

Lines changed: 39 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import (
1818
)
1919

2020
// ParseCommitWithSignature check if signature is good against keystore.
21-
func ParseCommitWithSignature(ctx context.Context, c *git.Commit) *asymkey_model.CommitVerification {
21+
func ParseCommitWithSignature(ctx context.Context, c *git.Commit, keysCache map[string][]*asymkey_model.GPGKey) *asymkey_model.CommitVerification {
2222
var committer *user_model.User
2323
if c.Committer != nil {
2424
var err error
@@ -42,10 +42,10 @@ func ParseCommitWithSignature(ctx context.Context, c *git.Commit) *asymkey_model
4242
}
4343
}
4444

45-
return ParseCommitWithSignatureCommitter(ctx, c, committer)
45+
return ParseCommitWithSignatureCommitter(ctx, c, committer, keysCache)
4646
}
4747

48-
func ParseCommitWithSignatureCommitter(ctx context.Context, c *git.Commit, committer *user_model.User) *asymkey_model.CommitVerification {
48+
func ParseCommitWithSignatureCommitter(ctx context.Context, c *git.Commit, committer *user_model.User, keysCache map[string][]*asymkey_model.GPGKey) *asymkey_model.CommitVerification {
4949
// If no signature just report the committer
5050
if c.Signature == nil {
5151
return &asymkey_model.CommitVerification{
@@ -82,7 +82,8 @@ func ParseCommitWithSignatureCommitter(ctx context.Context, c *git.Commit, commi
8282
committer,
8383
keyID,
8484
setting.AppName,
85-
""); commitVerification != nil {
85+
"",
86+
keysCache); commitVerification != nil {
8687
if commitVerification.Reason == asymkey_model.BadSignature {
8788
defaultReason = asymkey_model.BadSignature
8889
} else {
@@ -160,7 +161,7 @@ func ParseCommitWithSignatureCommitter(ctx context.Context, c *git.Commit, commi
160161
}
161162
if err := gpgSettings.LoadPublicKeyContent(); err != nil {
162163
log.Error("Error getting default signing key: %s %v", gpgSettings.KeyID, err)
163-
} else if commitVerification := VerifyWithGPGSettings(ctx, &gpgSettings, sig, c.Signature.Payload, committer, keyID); commitVerification != nil {
164+
} else if commitVerification := VerifyWithGPGSettings(ctx, &gpgSettings, sig, c.Signature.Payload, committer, keyID, keysCache); commitVerification != nil {
164165
if commitVerification.Reason == asymkey_model.BadSignature {
165166
defaultReason = asymkey_model.BadSignature
166167
} else {
@@ -175,7 +176,7 @@ func ParseCommitWithSignatureCommitter(ctx context.Context, c *git.Commit, commi
175176
} else if defaultGPGSettings == nil {
176177
log.Warn("Unable to get defaultGPGSettings for unattached commit: %s", c.ID.String())
177178
} else if defaultGPGSettings.Sign {
178-
if commitVerification := VerifyWithGPGSettings(ctx, defaultGPGSettings, sig, c.Signature.Payload, committer, keyID); commitVerification != nil {
179+
if commitVerification := VerifyWithGPGSettings(ctx, defaultGPGSettings, sig, c.Signature.Payload, committer, keyID, keysCache); commitVerification != nil {
179180
if commitVerification.Reason == asymkey_model.BadSignature {
180181
defaultReason = asymkey_model.BadSignature
181182
} else {
@@ -225,39 +226,48 @@ func checkKeyEmails(ctx context.Context, email string, keys ...*asymkey_model.GP
225226
return false, email
226227
}
227228

228-
func HashAndVerifyForKeyID(ctx context.Context, sig *packet.Signature, payload string, committer *user_model.User, keyID, name, email string) *asymkey_model.CommitVerification {
229+
func HashAndVerifyForKeyID(ctx context.Context, sig *packet.Signature, payload string, committer *user_model.User, keyID, name, email string, keysCache map[string][]*asymkey_model.GPGKey) *asymkey_model.CommitVerification {
229230
if keyID == "" {
230231
return nil
231232
}
232-
keys, err := db.Find[asymkey_model.GPGKey](ctx, asymkey_model.FindGPGKeyOptions{
233-
KeyID: keyID,
234-
IncludeSubKeys: true,
235-
})
236-
if err != nil {
237-
log.Error("GetGPGKeysByKeyID: %v", err)
238-
return &asymkey_model.CommitVerification{
239-
CommittingUser: committer,
240-
Verified: false,
241-
Reason: "gpg.error.failed_retrieval_gpg_keys",
233+
var err error
234+
keys, ok := keysCache[keyID]
235+
if !ok {
236+
keys, err = db.Find[asymkey_model.GPGKey](ctx, asymkey_model.FindGPGKeyOptions{
237+
KeyID: keyID,
238+
IncludeSubKeys: true,
239+
})
240+
if err != nil {
241+
log.Error("GetGPGKeysByKeyID: %v", err)
242+
return &asymkey_model.CommitVerification{
243+
CommittingUser: committer,
244+
Verified: false,
245+
Reason: "gpg.error.failed_retrieval_gpg_keys",
246+
}
242247
}
248+
keysCache[keyID] = keys
243249
}
244250
if len(keys) == 0 {
245251
return nil
246252
}
247253
for _, key := range keys {
248254
var primaryKeys []*asymkey_model.GPGKey
249255
if key.PrimaryKeyID != "" {
250-
primaryKeys, err = db.Find[asymkey_model.GPGKey](ctx, asymkey_model.FindGPGKeyOptions{
251-
KeyID: key.PrimaryKeyID,
252-
IncludeSubKeys: true,
253-
})
254-
if err != nil {
255-
log.Error("GetGPGKeysByKeyID: %v", err)
256-
return &asymkey_model.CommitVerification{
257-
CommittingUser: committer,
258-
Verified: false,
259-
Reason: "gpg.error.failed_retrieval_gpg_keys",
256+
primaryKeys, ok = keysCache[keyID]
257+
if !ok {
258+
primaryKeys, err = db.Find[asymkey_model.GPGKey](ctx, asymkey_model.FindGPGKeyOptions{
259+
KeyID: key.PrimaryKeyID,
260+
IncludeSubKeys: true,
261+
})
262+
if err != nil {
263+
log.Error("GetGPGKeysByKeyID: %v", err)
264+
return &asymkey_model.CommitVerification{
265+
CommittingUser: committer,
266+
Verified: false,
267+
Reason: "gpg.error.failed_retrieval_gpg_keys",
268+
}
260269
}
270+
keysCache[keyID] = primaryKeys
261271
}
262272
}
263273

@@ -297,9 +307,9 @@ func HashAndVerifyForKeyID(ctx context.Context, sig *packet.Signature, payload s
297307
}
298308
}
299309

300-
func VerifyWithGPGSettings(ctx context.Context, gpgSettings *git.GPGSettings, sig *packet.Signature, payload string, committer *user_model.User, keyID string) *asymkey_model.CommitVerification {
310+
func VerifyWithGPGSettings(ctx context.Context, gpgSettings *git.GPGSettings, sig *packet.Signature, payload string, committer *user_model.User, keyID string, keysCache map[string][]*asymkey_model.GPGKey) *asymkey_model.CommitVerification {
301311
// First try to find the key in the db
302-
if commitVerification := HashAndVerifyForKeyID(ctx, sig, payload, committer, gpgSettings.KeyID, gpgSettings.Name, gpgSettings.Email); commitVerification != nil {
312+
if commitVerification := HashAndVerifyForKeyID(ctx, sig, payload, committer, gpgSettings.KeyID, gpgSettings.Name, gpgSettings.Email, keysCache); commitVerification != nil {
303313
return commitVerification
304314
}
305315

services/asymkey/sign.go

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ func SignWikiCommit(ctx context.Context, repo *repo_model.Repository, u *user_mo
176176
if signingKey == "" {
177177
return false, "", nil, &ErrWontSign{noKey}
178178
}
179+
keysCache := make(map[string][]*asymkey_model.GPGKey)
179180

180181
Loop:
181182
for _, rule := range rules {
@@ -216,7 +217,7 @@ Loop:
216217
if commit.Signature == nil {
217218
return false, "", nil, &ErrWontSign{parentSigned}
218219
}
219-
verification := ParseCommitWithSignature(ctx, commit)
220+
verification := ParseCommitWithSignature(ctx, commit, keysCache)
220221
if !verification.Verified {
221222
return false, "", nil, &ErrWontSign{parentSigned}
222223
}
@@ -232,6 +233,7 @@ func SignCRUDAction(ctx context.Context, repoPath string, u *user_model.User, tm
232233
if signingKey == "" {
233234
return false, "", nil, &ErrWontSign{noKey}
234235
}
236+
keysCache := make(map[string][]*asymkey_model.GPGKey)
235237

236238
Loop:
237239
for _, rule := range rules {
@@ -272,7 +274,7 @@ Loop:
272274
if commit.Signature == nil {
273275
return false, "", nil, &ErrWontSign{parentSigned}
274276
}
275-
verification := ParseCommitWithSignature(ctx, commit)
277+
verification := ParseCommitWithSignature(ctx, commit, keysCache)
276278
if !verification.Verified {
277279
return false, "", nil, &ErrWontSign{parentSigned}
278280
}
@@ -297,6 +299,7 @@ func SignMerge(ctx context.Context, pr *issues_model.PullRequest, u *user_model.
297299

298300
var gitRepo *git.Repository
299301
var err error
302+
keysCache := make(map[string][]*asymkey_model.GPGKey)
300303

301304
Loop:
302305
for _, rule := range rules {
@@ -347,7 +350,7 @@ Loop:
347350
if err != nil {
348351
return false, "", nil, err
349352
}
350-
verification := ParseCommitWithSignature(ctx, commit)
353+
verification := ParseCommitWithSignature(ctx, commit, keysCache)
351354
if !verification.Verified {
352355
return false, "", nil, &ErrWontSign{baseSigned}
353356
}
@@ -363,7 +366,7 @@ Loop:
363366
if err != nil {
364367
return false, "", nil, err
365368
}
366-
verification := ParseCommitWithSignature(ctx, commit)
369+
verification := ParseCommitWithSignature(ctx, commit, keysCache)
367370
if !verification.Verified {
368371
return false, "", nil, &ErrWontSign{headSigned}
369372
}
@@ -379,7 +382,7 @@ Loop:
379382
if err != nil {
380383
return false, "", nil, err
381384
}
382-
verification := ParseCommitWithSignature(ctx, commit)
385+
verification := ParseCommitWithSignature(ctx, commit, keysCache)
383386
if !verification.Verified {
384387
return false, "", nil, &ErrWontSign{commitsSigned}
385388
}
@@ -393,7 +396,7 @@ Loop:
393396
return false, "", nil, err
394397
}
395398
for _, commit := range commitList {
396-
verification := ParseCommitWithSignature(ctx, commit)
399+
verification := ParseCommitWithSignature(ctx, commit, keysCache)
397400
if !verification.Verified {
398401
return false, "", nil, &ErrWontSign{commitsSigned}
399402
}

services/convert/convert.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,8 @@ func ToActionArtifact(repo *repo_model.Repository, art *actions_model.ActionArti
254254

255255
// ToVerification convert a git.Commit.Signature to an api.PayloadCommitVerification
256256
func ToVerification(ctx context.Context, c *git.Commit) *api.PayloadCommitVerification {
257-
verif := asymkey_service.ParseCommitWithSignature(ctx, c)
257+
keysCache := make(map[string][]*asymkey_model.GPGKey)
258+
verif := asymkey_service.ParseCommitWithSignature(ctx, c, keysCache)
258259
commitVerification := &api.PayloadCommitVerification{
259260
Verified: verif.Verified,
260261
Reason: verif.Reason,

services/git/commit.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ func ParseCommitsWithSignature(ctx context.Context, oldCommits []*user_model.Use
3333
return nil, err
3434
}
3535

36+
keysCache := make(map[string][]*asymkey_model.GPGKey)
37+
3638
for _, c := range oldCommits {
3739
committer, ok := emailUsers[c.Committer.Email]
3840
if !ok && c.Committer != nil {
@@ -44,7 +46,7 @@ func ParseCommitsWithSignature(ctx context.Context, oldCommits []*user_model.Use
4446

4547
signCommit := &asymkey_model.SignCommit{
4648
UserCommit: c,
47-
Verification: asymkey_service.ParseCommitWithSignatureCommitter(ctx, c.Commit, committer),
49+
Verification: asymkey_service.ParseCommitWithSignatureCommitter(ctx, c.Commit, committer, keysCache),
4850
}
4951

5052
_ = asymkey_model.CalculateTrustStatus(signCommit.Verification, repoTrustModel, isOwnerMemberCollaborator, &keyMap)

services/repository/files/commit.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package files
66
import (
77
"context"
88

9+
asymkey_model "code.gitea.io/gitea/models/asymkey"
910
repo_model "code.gitea.io/gitea/models/repo"
1011
"code.gitea.io/gitea/modules/git"
1112
"code.gitea.io/gitea/modules/structs"
@@ -24,7 +25,8 @@ func CountDivergingCommits(ctx context.Context, repo *repo_model.Repository, bra
2425
// GetPayloadCommitVerification returns the verification information of a commit
2526
func GetPayloadCommitVerification(ctx context.Context, commit *git.Commit) *structs.PayloadCommitVerification {
2627
verification := &structs.PayloadCommitVerification{}
27-
commitVerification := asymkey_service.ParseCommitWithSignature(ctx, commit)
28+
keysCache := make(map[string][]*asymkey_model.GPGKey)
29+
commitVerification := asymkey_service.ParseCommitWithSignature(ctx, commit, keysCache)
2830
if commit.Signature != nil {
2931
verification.Signature = commit.Signature.Signature
3032
verification.Payload = commit.Signature.Payload

services/repository/gitgraph/graph_models.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ func (graph *Graph) LoadAndProcessCommits(ctx context.Context, repository *repo_
9797

9898
emails := map[string]*user_model.User{}
9999
keyMap := map[string]bool{}
100+
keysCache := make(map[string][]*asymkey_model.GPGKey)
100101

101102
for _, c := range graph.Commits {
102103
if len(c.Rev) == 0 {
@@ -115,7 +116,7 @@ func (graph *Graph) LoadAndProcessCommits(ctx context.Context, repository *repo_
115116
}
116117
}
117118

118-
c.Verification = asymkey_service.ParseCommitWithSignature(ctx, c.Commit)
119+
c.Verification = asymkey_service.ParseCommitWithSignature(ctx, c.Commit, keysCache)
119120

120121
_ = asymkey_model.CalculateTrustStatus(c.Verification, repository.GetTrustModel(), func(user *user_model.User) (bool, error) {
121122
return repo_model.IsOwnerMemberCollaborator(ctx, repository, user.ID)

0 commit comments

Comments
 (0)