forked from
tangled.org/core
fork
Configure Feed
Select the types of activity you want to include in your feed.
Monorepo for Tangled
fork
Configure Feed
Select the types of activity you want to include in your feed.
1package commitverify
2
3import (
4 "log"
5
6 "github.com/go-git/go-git/v5/plumbing/object"
7 "tangled.org/core/appview/db"
8 "tangled.org/core/appview/models"
9 "tangled.org/core/crypto"
10 "tangled.org/core/types"
11)
12
13type verifiedCommit struct {
14 fingerprint string
15 hash string
16}
17
18type VerifiedCommits map[verifiedCommit]struct{}
19
20func (vcs VerifiedCommits) IsVerified(hash string) bool {
21 for vc := range vcs {
22 if vc.hash == hash {
23 return true
24 }
25 }
26 return false
27}
28
29func (vcs VerifiedCommits) Fingerprint(hash string) string {
30 for vc := range vcs {
31 if vc.hash == hash {
32 return vc.fingerprint
33 }
34 }
35 return ""
36}
37
38func GetVerifiedObjectCommits(e db.Execer, emailToDid map[string]string, commits []*object.Commit) (VerifiedCommits, error) {
39 ndCommits := []types.NiceDiff{}
40 for _, commit := range commits {
41 ndCommits = append(ndCommits, ObjectCommitToNiceDiff(commit))
42 }
43 return GetVerifiedCommits(e, emailToDid, ndCommits)
44}
45
46func GetVerifiedCommits(e db.Execer, emailToDid map[string]string, ndCommits []types.NiceDiff) (VerifiedCommits, error) {
47 vcs := VerifiedCommits{}
48
49 didPubkeyCache := make(map[string][]models.PublicKey)
50
51 for _, commit := range ndCommits {
52 c := commit.Commit
53
54 committerEmail := c.Committer.Email
55 if did, exists := emailToDid[committerEmail]; exists {
56 // check if we've already fetched public keys for this did
57 pubKeys, ok := didPubkeyCache[did]
58 if !ok {
59 // fetch and cache public keys
60 keys, err := db.GetPublicKeysForDid(e, did)
61 if err != nil {
62 log.Printf("failed to fetch pubkey for %s: %v", committerEmail, err)
63 continue
64 }
65 pubKeys = keys
66 didPubkeyCache[did] = pubKeys
67 }
68
69 // try to verify with any associated pubkeys
70 for _, pk := range pubKeys {
71 if _, ok := crypto.VerifyCommitSignature(pk.Key, commit); ok {
72
73 fp, err := crypto.SSHFingerprint(pk.Key)
74 if err != nil {
75 log.Println("error computing ssh fingerprint:", err)
76 }
77
78 vc := verifiedCommit{fingerprint: fp, hash: c.This}
79 vcs[vc] = struct{}{}
80 break
81 }
82 }
83
84 }
85 }
86
87 return vcs, nil
88}
89
90// ObjectCommitToNiceDiff is a compatibility function to convert a
91// commit object into a NiceDiff structure.
92func ObjectCommitToNiceDiff(c *object.Commit) types.NiceDiff {
93 var niceDiff types.NiceDiff
94
95 // set commit information
96 niceDiff.Commit.Message = c.Message
97 niceDiff.Commit.Author = c.Author
98 niceDiff.Commit.This = c.Hash.String()
99 niceDiff.Commit.Committer = c.Committer
100 niceDiff.Commit.Tree = c.TreeHash.String()
101 niceDiff.Commit.PGPSignature = c.PGPSignature
102
103 changeId, ok := c.ExtraHeaders["change-id"]
104 if ok {
105 niceDiff.Commit.ChangedId = string(changeId)
106 }
107
108 // set parent hash if available
109 if len(c.ParentHashes) > 0 {
110 niceDiff.Commit.Parent = c.ParentHashes[0].String()
111 }
112
113 // XXX: Stats and Diff fields are typically populated
114 // after fetching the actual diff information, which isn't
115 // directly available in the commit object itself.
116
117 return niceDiff
118}