-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcloudflare.go
150 lines (129 loc) · 4.49 KB
/
cloudflare.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package api
import (
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
"net/http"
"time"
"github.com/Diniboy1123/usque/internal"
"github.com/Diniboy1123/usque/models"
)
// Register creates a new user account by registering a WireGuard public key and generating a random Android-like device identifier.
// The WireGuard private key isn't stored anywhere, therefore it won't be usable. It's sole purpose is to mimic the Android app's registration process.
//
// This function sends a POST request to the API to register a new user and returns the created account data.
//
// Parameters:
// - model: string - The device model string to register. (e.g., "PC")
// - locale: string - The user's locale (e.g., "en-US").
//
// Returns:
// - models.AccountData: The account data returned from the registration process.
// - error: An error if registration fails at any step.
//
// Example:
//
// account, err := Register("PC", "en-US")
// if err != nil {
// log.Fatalf("Registration failed: %v", err)
// }
func Register(model, locale string) (models.AccountData, error) {
wgKey, err := internal.GenerateRandomWgPubkey()
if err != nil {
return models.AccountData{}, fmt.Errorf("failed to generate wg key: %v", err)
}
serial, err := internal.GenerateRandomAndroidSerial()
if err != nil {
return models.AccountData{}, fmt.Errorf("failed to generate serial: %v", err)
}
data := models.Registration{
Key: wgKey,
InstallID: "",
FcmToken: "",
Tos: internal.TimeAsCfString(time.Now()),
Model: model,
Serial: serial,
OsVersion: "",
KeyType: internal.KeyTypeWg,
TunType: internal.TunTypeWg,
Locale: locale,
}
jsonData, err := json.Marshal(data)
if err != nil {
return models.AccountData{}, fmt.Errorf("failed to marshal json: %v", err)
}
req, err := http.NewRequest("POST", internal.ApiUrl+"/"+internal.ApiVersion+"/reg", bytes.NewBuffer(jsonData))
if err != nil {
return models.AccountData{}, fmt.Errorf("failed to create request: %v", err)
}
for k, v := range internal.Headers {
req.Header.Set(k, v)
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return models.AccountData{}, fmt.Errorf("failed to send request: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return models.AccountData{}, fmt.Errorf("failed to register: %v", resp.Status)
}
var accountData models.AccountData
if err := json.NewDecoder(resp.Body).Decode(&accountData); err != nil {
return models.AccountData{}, fmt.Errorf("failed to decode response: %v", err)
}
return accountData, nil
}
// EnrollKey updates an existing user account with a new MASQUE public key.
//
// This function sends a PATCH request to update the user's account with a new key.
//
// Parameters:
// - accountData: models.AccountData - The account data of the user being updated.
// - pubKey: []byte - The new MASQUE public key in binary format.
// - deviceName: string - The name of the device to enroll. (optional)
//
// Returns:
// - models.AccountData: The updated account data.
// - error: An error if the update process fails.
//
// Example:
//
// updatedAccount, err := EnrollKey(account, pubKey)
// if err != nil {
// log.Fatalf("Key enrollment failed: %v", err)
// }
func EnrollKey(accountData models.AccountData, pubKey []byte, deviceName string) (models.AccountData, error) {
deviceUpdate := models.DeviceUpdate{
Key: base64.StdEncoding.EncodeToString(pubKey),
KeyType: internal.KeyTypeMasque,
TunType: internal.TunTypeMasque,
}
if deviceName != "" {
deviceUpdate.Name = deviceName
}
jsonData, err := json.Marshal(deviceUpdate)
if err != nil {
return models.AccountData{}, fmt.Errorf("failed to marshal json: %v", err)
}
req, err := http.NewRequest("PATCH", internal.ApiUrl+"/"+internal.ApiVersion+"/reg/"+accountData.ID, bytes.NewBuffer(jsonData))
if err != nil {
return models.AccountData{}, fmt.Errorf("failed to create request: %v", err)
}
for k, v := range internal.Headers {
req.Header.Set(k, v)
}
req.Header.Set("Authorization", "Bearer "+accountData.Token)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return models.AccountData{}, fmt.Errorf("failed to send request: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return models.AccountData{}, fmt.Errorf("failed to update: %v", resp.Status)
}
if err := json.NewDecoder(resp.Body).Decode(&accountData); err != nil {
return models.AccountData{}, fmt.Errorf("failed to decode response: %v", err)
}
return accountData, nil
}