Skip to content

Commit 53cd60b

Browse files
committed
add account methods implementation
1 parent e026302 commit 53cd60b

File tree

4 files changed

+203
-15
lines changed

4 files changed

+203
-15
lines changed

node-registrar/client/account.go

Lines changed: 190 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,215 @@
11
package client
22

33
import (
4+
"bytes"
5+
"encoding/base64"
6+
"encoding/json"
47
"fmt"
8+
"net/http"
9+
"net/url"
10+
"time"
11+
12+
"github.com/pkg/errors"
513
)
614

715
var ErrorAccountNotFround = fmt.Errorf("failed to get requested account from node regiatrar")
816

917
func (c RegistrarClient) CreateAccount(relays []string, rmbEncKey string) (account Account, err error) {
10-
return c.createTwin(relays, rmbEncKey)
18+
return c.createAccount(relays, rmbEncKey)
19+
}
20+
21+
func (c RegistrarClient) GetAccount(id uint64) (account Account, err error) {
22+
return c.getAccount(id)
23+
}
24+
25+
func (c RegistrarClient) GetAccountByPK(pk []byte) (account Account, err error) {
26+
return c.getAccountByPK(pk)
1127
}
1228

1329
func (c RegistrarClient) UpdateAccount(relays []string, rmbEncKey string) (err error) {
14-
return
30+
return c.updateAccount(relays, rmbEncKey)
31+
}
32+
33+
func (c RegistrarClient) EnsureAccount(pk []byte, relays []string, rmbEncKey string) (account Account, err error) {
34+
return c.ensureAccount(pk, relays, rmbEncKey)
1535
}
1636

17-
func (c RegistrarClient) EnsureAccount(pk []byte) (account Account, err error) {
37+
func (c *RegistrarClient) createAccount(relays []string, rmbEncKey string) (result Account, err error) {
38+
url, err := url.JoinPath(c.baseURL, "accounts")
39+
if err != nil {
40+
return result, errors.Wrap(err, "failed to construct registrar url")
41+
}
42+
43+
publicKeyBase64 := base64.StdEncoding.EncodeToString(c.keyPair.publicKey)
44+
45+
timestamp := time.Now().Unix()
46+
signature := c.signRequest(timestamp)
47+
48+
account := map[string]any{
49+
"public_key": publicKeyBase64,
50+
"signature": signature,
51+
"timestamp": timestamp,
52+
"rmb_enc_key": rmbEncKey,
53+
"relays": relays,
54+
}
55+
56+
var body bytes.Buffer
57+
err = json.NewEncoder(&body).Encode(account)
58+
if err != nil {
59+
return result, errors.Wrap(err, "failed to parse request body")
60+
}
61+
62+
resp, err := c.httpClient.Post(url, "application/json", &body)
63+
if err != nil {
64+
return result, errors.Wrap(err, "failed to send request to the registrar")
65+
}
66+
67+
if resp.StatusCode != http.StatusCreated {
68+
err = parseResponseError(resp.Body)
69+
return result, errors.Wrapf(err, "failed to create account with status %s", resp.Status)
70+
}
71+
defer resp.Body.Close()
72+
73+
err = json.NewDecoder(resp.Body).Decode(&result)
74+
75+
c.twinID = result.TwinID
1876
return
1977
}
2078

21-
func (c RegistrarClient) GetAccount(id uint64) (account Account, err error) {
79+
func (c RegistrarClient) getAccount(id uint64) (account Account, err error) {
80+
url, err := url.JoinPath(c.baseURL, "accounts")
81+
if err != nil {
82+
return account, errors.Wrap(err, "failed to construct registrar url")
83+
}
84+
85+
req, err := http.NewRequest("GET", url, nil)
86+
if err != nil {
87+
return
88+
}
89+
90+
q := req.URL.Query()
91+
q.Add("twin_id", fmt.Sprint(id))
92+
req.URL.RawQuery = q.Encode()
93+
94+
resp, err := c.httpClient.Do(req)
95+
if err != nil {
96+
return
97+
}
98+
99+
if resp == nil {
100+
return account, errors.New("failed to get account, no response received")
101+
}
102+
103+
if resp.StatusCode == http.StatusNotFound {
104+
return account, ErrorAccountNotFround
105+
}
106+
107+
if resp.StatusCode != http.StatusOK {
108+
err = parseResponseError(resp.Body)
109+
return account, errors.Wrapf(err, "failed to get account by twin id with status code %s", resp.Status)
110+
}
111+
defer resp.Body.Close()
112+
113+
err = json.NewDecoder(resp.Body).Decode(&account)
22114
return
23115
}
24116

25-
func (c RegistrarClient) GetAccountByPK(pk []byte) (account Account, err error) {
117+
func (c RegistrarClient) updateAccount(relays []string, rmbEncKey string) (err error) {
118+
url, err := url.JoinPath(c.baseURL, "accounts", fmt.Sprint(c.twinID))
119+
if err != nil {
120+
return errors.Wrap(err, "failed to construct registrar url")
121+
}
122+
123+
acc := map[string]any{}
124+
125+
if len(relays) != 0 {
126+
acc["relays"] = relays
127+
}
128+
129+
if len(rmbEncKey) != 0 {
130+
acc["rmb_enc_key"] = rmbEncKey
131+
}
132+
133+
var body bytes.Buffer
134+
err = json.NewEncoder(&body).Encode(acc)
135+
if err != nil {
136+
return errors.Wrap(err, "failed to parse request body")
137+
}
138+
139+
req, err := http.NewRequest("PATCH", url, &body)
140+
if err != nil {
141+
return
142+
}
143+
144+
req.Header.Set("X-Auth", c.signRequest(time.Now().Unix()))
145+
req.Header.Set("Content-Type", "application/json")
146+
147+
resp, err := c.httpClient.Do(req)
148+
if err != nil {
149+
fmt.Println("Error sending request:", err)
150+
return
151+
}
152+
153+
if resp == nil {
154+
return errors.New("failed to update account, no response received")
155+
}
156+
defer resp.Body.Close()
157+
158+
if resp.StatusCode != http.StatusOK {
159+
return parseResponseError(resp.Body)
160+
}
161+
26162
return
27163
}
28164

29-
func (c *RegistrarClient) createTwin(relays []string, rmbEncKey string) (result Account, err error) {
165+
func (c RegistrarClient) getAccountByPK(pk []byte) (account Account, err error) {
166+
url, err := url.JoinPath(c.baseURL, "accounts", fmt.Sprint(c.twinID))
167+
if err != nil {
168+
return account, errors.Wrap(err, "failed to construct registrar url")
169+
}
170+
171+
publicKeyBase64 := base64.StdEncoding.EncodeToString(pk)
172+
173+
req, err := http.NewRequest("GET", url, nil)
174+
if err != nil {
175+
return account, err
176+
}
177+
178+
q := req.URL.Query()
179+
q.Add("public_key", publicKeyBase64)
180+
req.URL.RawQuery = q.Encode()
181+
182+
resp, err := c.httpClient.Do(req)
183+
if err != nil {
184+
return account, err
185+
}
186+
187+
if resp == nil {
188+
return account, errors.New("no response received")
189+
}
190+
defer resp.Body.Close()
191+
192+
if resp.StatusCode == http.StatusNotFound {
193+
return account, ErrorAccountNotFround
194+
}
195+
196+
if resp.StatusCode != http.StatusOK {
197+
err = parseResponseError(resp.Body)
198+
return account, errors.Wrapf(err, "failed to get account by public_key with status code %s", resp.Status)
199+
}
200+
201+
err = json.NewDecoder(resp.Body).Decode(&account)
202+
203+
return account, err
204+
}
205+
206+
func (c RegistrarClient) ensureAccount(pk []byte, relays []string, rmbEncKey string) (account Account, err error) {
207+
account, err = c.GetAccountByPK(pk)
208+
if errors.Is(err, ErrorAccountNotFround) {
209+
return c.CreateAccount(relays, rmbEncKey)
210+
} else if err != nil {
211+
return account, errors.Wrap(err, "failed to get account from the registrar")
212+
}
213+
30214
return
31215
}

node-registrar/client/client.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,14 @@ import (
77
"github.com/pkg/errors"
88
)
99

10+
type keyPair struct {
11+
privateKey ed25519.PrivateKey
12+
publicKey ed25519.PublicKey
13+
}
14+
1015
type RegistrarClient struct {
1116
httpClient http.Client
12-
privateKey ed25519.PrivateKey
17+
keyPair keyPair
1318
nodeID uint64
1419
twinID uint64
1520
baseURL string
@@ -19,18 +24,18 @@ func NewRegistrarClient(baseURL string, privateKey []byte) (cli RegistrarClient,
1924
client := http.DefaultClient
2025

2126
sk := ed25519.NewKeyFromSeed(privateKey)
22-
pk, ok := sk.Public().(ed25519.PublicKey)
27+
publicKey, ok := sk.Public().(ed25519.PublicKey)
2328
if !ok {
2429
return cli, errors.Wrap(err, "failed to get public key of provided private key")
2530
}
2631

2732
cli = RegistrarClient{
2833
httpClient: *client,
29-
privateKey: privateKey,
34+
keyPair: keyPair{privateKey, publicKey},
3035
baseURL: baseURL,
3136
}
3237

33-
account, err := cli.GetAccountByPK(pk)
38+
account, err := cli.GetAccountByPK(publicKey)
3439
if errors.Is(err, ErrorAccountNotFround) {
3540
return cli, nil
3641
} else if err != nil {

node-registrar/client/utils.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,14 @@ import (
66
"encoding/json"
77
"fmt"
88
"io"
9-
"time"
109

1110
"github.com/pkg/errors"
1211
)
1312

14-
func (c RegistrarClient) signRequest() (authHeader string) {
15-
timestamp := time.Now().Unix()
13+
func (c RegistrarClient) signRequest(timestamp int64) (authHeader string) {
1614
challenge := []byte(fmt.Sprintf("%d:%v", timestamp, c.twinID))
1715

18-
signature := ed25519.Sign(c.privateKey, challenge)
16+
signature := ed25519.Sign(c.keyPair.privateKey, challenge)
1917

2018
authHeader = fmt.Sprintf(
2119
"%s:%s",

node-registrar/client/zos_version.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"net/http"
88
"net/url"
99
"strings"
10+
"time"
1011

1112
"github.com/pkg/errors"
1213
)
@@ -90,7 +91,7 @@ func (c RegistrarClient) setZosVersion(v string, safeToUpgrade bool) (err error)
9091
return errors.Wrap(err, "failed to construct http request to the registrar")
9192
}
9293

93-
req.Header.Set("X-Auth", c.signRequest())
94+
req.Header.Set("X-Auth", c.signRequest(time.Now().Unix()))
9495
req.Header.Set("Content-Type", "application/json")
9596

9697
resp, err := c.httpClient.Do(req)

0 commit comments

Comments
 (0)