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