133 lines
2.6 kB
1
package state
2
3
import (
4
"bytes"
5
"crypto/hmac"
6
"crypto/sha256"
7
"encoding/hex"
8
"encoding/json"
9
"fmt"
10
"net/http"
11
"net/url"
12
"time"
13
)
14
15
type SignerTransport struct {
16
Secret string
17
}
18
19
func (s SignerTransport) RoundTrip(req *http.Request) (*http.Response, error) {
20
timestamp := time.Now().Format(time.RFC3339)
21
mac := hmac.New(sha256.New, []byte(s.Secret))
22
message := req.Method + req.URL.Path + timestamp
23
mac.Write([]byte(message))
24
signature := hex.EncodeToString(mac.Sum(nil))
25
req.Header.Set("X-Signature", signature)
26
req.Header.Set("X-Timestamp", timestamp)
27
return http.DefaultTransport.RoundTrip(req)
28
}
29
30
type SignedClient struct {
31
Secret string
32
Url *url.URL
33
client *http.Client
34
}
35
36
func NewSignedClient(domain, secret string) (*SignedClient, error) {
37
client := &http.Client{
38
Timeout: 5 * time.Second,
39
Transport: SignerTransport{
40
Secret: secret,
41
},
42
}
43
44
url, err := url.Parse(fmt.Sprintf("http://%s", domain))
45
if err != nil {
46
return nil, err
47
}
48
49
signedClient := &SignedClient{
50
Secret: secret,
51
client: client,
52
Url: url,
53
}
54
55
return signedClient, nil
56
}
57
58
func (s *SignedClient) newRequest(method, endpoint string, body []byte) (*http.Request, error) {
59
return http.NewRequest(method, s.Url.JoinPath(endpoint).String(), bytes.NewReader(body))
60
}
61
62
func (s *SignedClient) Init(did string) (*http.Response, error) {
63
const (
64
Method = "POST"
65
Endpoint = "/init"
66
)
67
68
body, _ := json.Marshal(map[string]interface{}{
69
"did": did,
70
})
71
72
req, err := s.newRequest(Method, Endpoint, body)
73
if err != nil {
74
return nil, err
75
}
76
77
return s.client.Do(req)
78
}
79
80
func (s *SignedClient) NewRepo(did, repoName string) (*http.Response, error) {
81
const (
82
Method = "PUT"
83
Endpoint = "/repo/new"
84
)
85
86
body, _ := json.Marshal(map[string]interface{}{
87
"did": did,
88
"name": repoName,
89
})
90
91
req, err := s.newRequest(Method, Endpoint, body)
92
if err != nil {
93
return nil, err
94
}
95
96
return s.client.Do(req)
97
}
98
99
func (s *SignedClient) AddMember(did string) (*http.Response, error) {
100
const (
101
Method = "PUT"
102
Endpoint = "/member/add"
103
)
104
105
body, _ := json.Marshal(map[string]interface{}{
106
"did": did,
107
})
108
109
req, err := s.newRequest(Method, Endpoint, body)
110
if err != nil {
111
return nil, err
112
}
113
114
return s.client.Do(req)
115
}
116
117
func (s *SignedClient) AddCollaborator(ownerDid, repoName, memberDid string) (*http.Response, error) {
118
const (
119
Method = "POST"
120
)
121
endpoint := fmt.Sprintf("/%s/%s/collaborator/add", ownerDid, repoName)
122
123
body, _ := json.Marshal(map[string]interface{}{
124
"did": memberDid,
125
})
126
127
req, err := s.newRequest(Method, endpoint, body)
128
if err != nil {
129
return nil, err
130
}
131
132
return s.client.Do(req)
133
}
134