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