1package validate
2
3import (
4 "fmt"
5 "testing"
6
7 "github.com/MichaelMure/git-bug/cache"
8 "github.com/MichaelMure/git-bug/identity"
9 "github.com/MichaelMure/git-bug/repository"
10 "github.com/stretchr/testify/require"
11)
12
13func checkAddIdentity(t *testing.T, backend *cache.RepoCache, name, email, armoredPubkey string) *cache.IdentityCache {
14 key, err := identity.NewKey(armoredPubkey)
15 require.NoError(t, err)
16
17 id, err := backend.NewIdentityWithKeyRaw(name, email, "", "", nil, key)
18 require.NoError(t, err)
19
20 return id
21}
22
23func checkValidator(t *testing.T, backend *cache.RepoCache, errorMsg, firstKey string) {
24 validator, err := NewValidator(backend)
25 if errorMsg == "" {
26 require.NoError(t, err)
27 if firstKey == "" {
28 require.Nil(t, validator.FirstKey)
29 } else {
30 require.Equal(t, firstKey, validator.FirstKey.ArmoredPublicKey)
31 }
32 } else {
33 require.EqualError(t, err, errorMsg)
34 }
35}
36
37func checkAddKey(t *testing.T, id *cache.IdentityCache, armoredKey string) {
38 key, err := identity.NewKey(armoredKey)
39 require.NoError(t, err)
40
41 err = id.Mutate(func(m identity.Mutator) identity.Mutator {
42 m.Keys = append(m.Keys, key)
43 return m
44 })
45 require.NoError(t, err)
46
47 err = id.Commit()
48 require.NoError(t, err)
49}
50
51func TestNewValidator_EmptyRepo(t *testing.T) {
52 repo := repository.CreateTestRepo(false)
53 defer repository.CleanupTestRepos(t, repo)
54
55 backend, err := cache.NewRepoCache(repo)
56 require.NoError(t, err)
57
58 checkValidator(t, backend, "", "")
59 validator, err := NewValidator(backend)
60 require.NoError(t, err)
61 require.Nil(t, validator.FirstKey)
62}
63
64func TestNewValidator_OneIdentity(t *testing.T) {
65 repo := repository.CreateTestRepo(false)
66 defer repository.CleanupTestRepos(t, repo)
67
68 backend, err := cache.NewRepoCache(repo)
69 require.NoError(t, err)
70
71 armoredPubkey := repository.SetupSigningKey(t, repo, "a@e.org")
72
73 _ = checkAddIdentity(t, backend, "A", "a@e.org", armoredPubkey)
74 checkValidator(t, backend, "", armoredPubkey)
75}
76
77func TestNewValidator_TwoSeparateIdentities(t *testing.T) {
78 repo := repository.CreateTestRepo(false)
79 defer repository.CleanupTestRepos(t, repo)
80
81 backend, err := cache.NewRepoCache(repo)
82 require.NoError(t, err)
83
84 armoredPubkey := repository.SetupSigningKey(t, repo, "a@e.org")
85 _ = checkAddIdentity(t, backend, "A", "a@e.org", armoredPubkey)
86
87 armoredPubkey2 := repository.SetupSigningKey(t, repo, "b@e.org")
88 id2 := checkAddIdentity(t, backend, "B", "b@e.org", armoredPubkey2)
89
90 msg := fmt.Sprintf("failed to validate identities: invalid identity %s (%s): invalid signature for commit %s: no key can verify the signature",
91 id2.Id(), id2.Email(), id2.Versions()[0].CommitHash())
92 checkValidator(t, backend, msg, "")
93}
94
95func TestNewValidator_IdentityWithSameKeyTwice(t *testing.T) {
96 repo := repository.CreateTestRepo(false)
97 defer repository.CleanupTestRepos(t, repo)
98
99 backend, err := cache.NewRepoCache(repo)
100 require.NoError(t, err)
101
102 armoredPubkey := repository.SetupSigningKey(t, repo, "a@e.org")
103 id1 := checkAddIdentity(t, backend, "A", "a@e.org", armoredPubkey)
104
105 checkAddKey(t, id1, armoredPubkey)
106
107 msg := fmt.Sprintf("failed to read identity versions: keys with identical keyId introduced in commits %s and %s",
108 id1.Versions()[0].CommitHash(), id1.Versions()[1].CommitHash())
109 checkValidator(t, backend, msg, "")
110}
111
112func TestNewValidator_TwoIdentitiesWithSameKey(t *testing.T) {
113 repo := repository.CreateTestRepo(false)
114 defer repository.CleanupTestRepos(t, repo)
115
116 backend, err := cache.NewRepoCache(repo)
117 require.NoError(t, err)
118
119 armoredPubkey := repository.SetupSigningKey(t, repo, "a@e.org")
120 id1 := checkAddIdentity(t, backend, "A", "a@e.org", armoredPubkey)
121
122 id2 := checkAddIdentity(t, backend, "B", "b@e.org", armoredPubkey)
123
124 _, err = NewValidator(backend)
125 require.EqualError(t, err,
126 fmt.Sprintf("failed to read identity versions: keys with identical keyId introduced in commits %s and %s",
127 id1.Versions()[0].CommitHash(), id2.Versions()[0].CommitHash()))
128}
129
130func TestNewValidator_TwoIdentitiesTwoVersions(t *testing.T) {
131 repo := repository.CreateTestRepo(false)
132 defer repository.CleanupTestRepos(t, repo)
133
134 backend, err := cache.NewRepoCache(repo)
135 require.NoError(t, err)
136
137 armoredPubkey := repository.SetupSigningKey(t, repo, "a@e.org")
138 id1 := checkAddIdentity(t, backend, "A", "a@e.org", armoredPubkey)
139 checkValidator(t, backend, "", armoredPubkey)
140
141 armoredPubkey2 := repository.CreatePubkey(t)
142 id2 := checkAddIdentity(t, backend, "B", "b@e.org", armoredPubkey2)
143
144 armoredPubkey3 := repository.CreatePubkey(t)
145 checkAddKey(t, id1, armoredPubkey3)
146
147 armoredPubkey4 := repository.CreatePubkey(t)
148 checkAddKey(t, id2, armoredPubkey4)
149
150 checkValidator(t, backend, "", armoredPubkey)
151}
152
153func TestNewValidator_WrongEmail(t *testing.T) {
154 repo := repository.CreateTestRepo(false)
155 defer repository.CleanupTestRepos(t, repo)
156
157 backend, err := cache.NewRepoCache(repo)
158 require.NoError(t, err)
159
160 armoredPubkey := repository.SetupSigningKey(t, repo, "a@e.org")
161 repository.SetupKey(t, repo, "x@a.org", "", "")
162 id1 := checkAddIdentity(t, backend, "A", "a@e.org", armoredPubkey)
163
164 msg := fmt.Sprintf("failed to validate identities: invalid identity %s (%s): invalid signature for commit %s: git commit committer-email does not match the identity-email: x@a.org vs a@e.org",
165 id1.Id(), id1.Email(), id1.Versions()[0].CommitHash())
166 checkValidator(t, backend, msg, armoredPubkey)
167}