axiodb 20.3.2 → 20.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/.graphifyignore +0 -12
- package/cli/VERSION +0 -1
- package/cli/cmd/auth_management.go +0 -68
- package/cli/cmd/collection.go +0 -169
- package/cli/cmd/connect.go +0 -597
- package/cli/cmd/db.go +0 -171
- package/cli/cmd/db_export.go +0 -66
- package/cli/cmd/db_import.go +0 -84
- package/cli/cmd/document.go +0 -409
- package/cli/cmd/health.go +0 -19
- package/cli/cmd/index.go +0 -101
- package/cli/cmd/ping.go +0 -36
- package/cli/cmd/root.go +0 -38
- package/cli/cmd/transaction.go +0 -191
- package/cli/cmd/version.go +0 -27
- package/cli/go.mod +0 -15
- package/cli/go.sum +0 -20
- package/cli/internal/config/config.go +0 -120
- package/cli/main.go +0 -7
- package/cli/pkg/commands/collection.go +0 -68
- package/cli/pkg/commands/db.go +0 -62
- package/cli/pkg/commands/document.go +0 -203
- package/cli/pkg/commands/health.go +0 -18
- package/cli/pkg/commands/index.go +0 -51
- package/cli/pkg/commands/transaction.go +0 -84
- package/cli/pkg/httpclient/client.go +0 -236
- package/cli/pkg/protocol/auth.go +0 -46
- package/cli/pkg/protocol/client.go +0 -174
- package/cli/pkg/protocol/message.go +0 -75
- package/lib/engine/cli/worker_process.d.ts +0 -6
- package/lib/engine/cli/worker_process.js +0 -63
- package/lib/engine/cli/worker_process.js.map +0 -1
- package/opencode.json +0 -9
|
@@ -1,203 +0,0 @@
|
|
|
1
|
-
package commands
|
|
2
|
-
|
|
3
|
-
import (
|
|
4
|
-
"fmt"
|
|
5
|
-
|
|
6
|
-
"github.com/nexoral/axiodb-cli/pkg/protocol"
|
|
7
|
-
)
|
|
8
|
-
|
|
9
|
-
func InsertDocument(client *protocol.Client, dbName, collectionName string, data interface{}) (*protocol.Response, error) {
|
|
10
|
-
resp, err := client.Send("INSERT_DOCUMENT", map[string]interface{}{
|
|
11
|
-
"dbName": dbName,
|
|
12
|
-
"collectionName": collectionName,
|
|
13
|
-
"data": data,
|
|
14
|
-
})
|
|
15
|
-
if err != nil {
|
|
16
|
-
return nil, fmt.Errorf("insert document: %w", err)
|
|
17
|
-
}
|
|
18
|
-
if resp.StatusCode >= 400 {
|
|
19
|
-
return nil, fmt.Errorf("insert document failed: %s", resp.Error)
|
|
20
|
-
}
|
|
21
|
-
return resp, nil
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
func InsertManyDocuments(client *protocol.Client, dbName, collectionName string, documents interface{}) (*protocol.Response, error) {
|
|
25
|
-
resp, err := client.Send("INSERT_MANY_DOCUMENTS", map[string]interface{}{
|
|
26
|
-
"dbName": dbName,
|
|
27
|
-
"collectionName": collectionName,
|
|
28
|
-
"documents": documents,
|
|
29
|
-
})
|
|
30
|
-
if err != nil {
|
|
31
|
-
return nil, fmt.Errorf("insert many documents: %w", err)
|
|
32
|
-
}
|
|
33
|
-
if resp.StatusCode >= 400 {
|
|
34
|
-
return nil, fmt.Errorf("insert many documents failed: %s", resp.Error)
|
|
35
|
-
}
|
|
36
|
-
return resp, nil
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
type QueryOptions struct {
|
|
40
|
-
Query interface{}
|
|
41
|
-
Limit int
|
|
42
|
-
Skip int
|
|
43
|
-
Sort interface{}
|
|
44
|
-
FindOne bool
|
|
45
|
-
Hint string
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
func QueryDocuments(client *protocol.Client, dbName, collectionName string, opts QueryOptions) (*protocol.Response, error) {
|
|
49
|
-
params := map[string]interface{}{
|
|
50
|
-
"dbName": dbName,
|
|
51
|
-
"collectionName": collectionName,
|
|
52
|
-
}
|
|
53
|
-
if opts.Query != nil {
|
|
54
|
-
params["query"] = opts.Query
|
|
55
|
-
}
|
|
56
|
-
if opts.Limit > 0 {
|
|
57
|
-
params["limit"] = opts.Limit
|
|
58
|
-
}
|
|
59
|
-
if opts.Skip > 0 {
|
|
60
|
-
params["skip"] = opts.Skip
|
|
61
|
-
}
|
|
62
|
-
if opts.Sort != nil {
|
|
63
|
-
params["sort"] = opts.Sort
|
|
64
|
-
}
|
|
65
|
-
if opts.FindOne {
|
|
66
|
-
params["findOne"] = true
|
|
67
|
-
}
|
|
68
|
-
if opts.Hint != "" {
|
|
69
|
-
params["hint"] = opts.Hint
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
resp, err := client.Send("QUERY_DOCUMENTS", params)
|
|
73
|
-
if err != nil {
|
|
74
|
-
return nil, fmt.Errorf("query documents: %w", err)
|
|
75
|
-
}
|
|
76
|
-
if resp.StatusCode >= 400 {
|
|
77
|
-
return nil, fmt.Errorf("query documents failed: %s", resp.Error)
|
|
78
|
-
}
|
|
79
|
-
return resp, nil
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
func QueryByID(client *protocol.Client, dbName, collectionName, id string) (*protocol.Response, error) {
|
|
83
|
-
resp, err := client.Send("QUERY_BY_ID", map[string]interface{}{
|
|
84
|
-
"dbName": dbName,
|
|
85
|
-
"collectionName": collectionName,
|
|
86
|
-
"id": id,
|
|
87
|
-
})
|
|
88
|
-
if err != nil {
|
|
89
|
-
return nil, fmt.Errorf("query by id: %w", err)
|
|
90
|
-
}
|
|
91
|
-
if resp.StatusCode >= 400 {
|
|
92
|
-
return nil, fmt.Errorf("query by id failed: %s", resp.Error)
|
|
93
|
-
}
|
|
94
|
-
return resp, nil
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
func FindDocumentsByIDs(client *protocol.Client, dbName, collectionName string, ids interface{}) (*protocol.Response, error) {
|
|
98
|
-
resp, err := client.Send("FIND_BY_IDS", map[string]interface{}{
|
|
99
|
-
"dbName": dbName,
|
|
100
|
-
"collectionName": collectionName,
|
|
101
|
-
"ids": ids,
|
|
102
|
-
})
|
|
103
|
-
if err != nil {
|
|
104
|
-
return nil, fmt.Errorf("find documents by ids: %w", err)
|
|
105
|
-
}
|
|
106
|
-
if resp.StatusCode >= 400 {
|
|
107
|
-
return nil, fmt.Errorf("find documents by ids failed: %s", resp.Error)
|
|
108
|
-
}
|
|
109
|
-
return resp, nil
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
func UpdateDocumentByID(client *protocol.Client, dbName, collectionName, id string, updateData interface{}) (*protocol.Response, error) {
|
|
113
|
-
resp, err := client.Send("UPDATE_DOCUMENT_BY_ID", map[string]interface{}{
|
|
114
|
-
"dbName": dbName,
|
|
115
|
-
"collectionName": collectionName,
|
|
116
|
-
"id": id,
|
|
117
|
-
"updateData": updateData,
|
|
118
|
-
})
|
|
119
|
-
if err != nil {
|
|
120
|
-
return nil, fmt.Errorf("update document: %w", err)
|
|
121
|
-
}
|
|
122
|
-
if resp.StatusCode >= 400 {
|
|
123
|
-
return nil, fmt.Errorf("update document failed: %s", resp.Error)
|
|
124
|
-
}
|
|
125
|
-
return resp, nil
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
func UpdateDocumentsByQuery(client *protocol.Client, dbName, collectionName string, query, updateData interface{}, updateOne bool) (*protocol.Response, error) {
|
|
129
|
-
resp, err := client.Send("UPDATE_DOCUMENTS_BY_QUERY", map[string]interface{}{
|
|
130
|
-
"dbName": dbName,
|
|
131
|
-
"collectionName": collectionName,
|
|
132
|
-
"query": query,
|
|
133
|
-
"updateData": updateData,
|
|
134
|
-
"updateOne": updateOne,
|
|
135
|
-
})
|
|
136
|
-
if err != nil {
|
|
137
|
-
return nil, fmt.Errorf("update documents by query: %w", err)
|
|
138
|
-
}
|
|
139
|
-
if resp.StatusCode >= 400 {
|
|
140
|
-
return nil, fmt.Errorf("update documents by query failed: %s", resp.Error)
|
|
141
|
-
}
|
|
142
|
-
return resp, nil
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
func DeleteDocumentByID(client *protocol.Client, dbName, collectionName, id string) (*protocol.Response, error) {
|
|
146
|
-
resp, err := client.Send("DELETE_DOCUMENT_BY_ID", map[string]interface{}{
|
|
147
|
-
"dbName": dbName,
|
|
148
|
-
"collectionName": collectionName,
|
|
149
|
-
"id": id,
|
|
150
|
-
})
|
|
151
|
-
if err != nil {
|
|
152
|
-
return nil, fmt.Errorf("delete document: %w", err)
|
|
153
|
-
}
|
|
154
|
-
if resp.StatusCode >= 400 {
|
|
155
|
-
return nil, fmt.Errorf("delete document failed: %s", resp.Error)
|
|
156
|
-
}
|
|
157
|
-
return resp, nil
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
func DeleteDocumentsByQuery(client *protocol.Client, dbName, collectionName string, query interface{}, deleteOne bool) (*protocol.Response, error) {
|
|
161
|
-
resp, err := client.Send("DELETE_DOCUMENTS_BY_QUERY", map[string]interface{}{
|
|
162
|
-
"dbName": dbName,
|
|
163
|
-
"collectionName": collectionName,
|
|
164
|
-
"query": query,
|
|
165
|
-
"deleteOne": deleteOne,
|
|
166
|
-
})
|
|
167
|
-
if err != nil {
|
|
168
|
-
return nil, fmt.Errorf("delete documents by query: %w", err)
|
|
169
|
-
}
|
|
170
|
-
if resp.StatusCode >= 400 {
|
|
171
|
-
return nil, fmt.Errorf("delete documents by query failed: %s", resp.Error)
|
|
172
|
-
}
|
|
173
|
-
return resp, nil
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
func Aggregate(client *protocol.Client, dbName, collectionName string, pipeline interface{}) (*protocol.Response, error) {
|
|
177
|
-
resp, err := client.Send("AGGREGATE", map[string]interface{}{
|
|
178
|
-
"dbName": dbName,
|
|
179
|
-
"collectionName": collectionName,
|
|
180
|
-
"pipeline": pipeline,
|
|
181
|
-
})
|
|
182
|
-
if err != nil {
|
|
183
|
-
return nil, fmt.Errorf("aggregate: %w", err)
|
|
184
|
-
}
|
|
185
|
-
if resp.StatusCode >= 400 {
|
|
186
|
-
return nil, fmt.Errorf("aggregate failed: %s", resp.Error)
|
|
187
|
-
}
|
|
188
|
-
return resp, nil
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
func TotalDocuments(client *protocol.Client, dbName, collectionName string) (*protocol.Response, error) {
|
|
192
|
-
resp, err := client.Send("TOTAL_DOCUMENTS", map[string]interface{}{
|
|
193
|
-
"dbName": dbName,
|
|
194
|
-
"collectionName": collectionName,
|
|
195
|
-
})
|
|
196
|
-
if err != nil {
|
|
197
|
-
return nil, fmt.Errorf("total documents: %w", err)
|
|
198
|
-
}
|
|
199
|
-
if resp.StatusCode >= 400 {
|
|
200
|
-
return nil, fmt.Errorf("total documents failed: %s", resp.Error)
|
|
201
|
-
}
|
|
202
|
-
return resp, nil
|
|
203
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
package commands
|
|
2
|
-
|
|
3
|
-
import (
|
|
4
|
-
"fmt"
|
|
5
|
-
|
|
6
|
-
"github.com/nexoral/axiodb-cli/pkg/protocol"
|
|
7
|
-
)
|
|
8
|
-
|
|
9
|
-
func Health(client *protocol.Client) (*protocol.Response, error) {
|
|
10
|
-
resp, err := client.Send("HEALTH", nil)
|
|
11
|
-
if err != nil {
|
|
12
|
-
return nil, fmt.Errorf("get health: %w", err)
|
|
13
|
-
}
|
|
14
|
-
if resp.StatusCode >= 400 {
|
|
15
|
-
return nil, fmt.Errorf("get health failed: %s", resp.Error)
|
|
16
|
-
}
|
|
17
|
-
return resp, nil
|
|
18
|
-
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
package commands
|
|
2
|
-
|
|
3
|
-
import (
|
|
4
|
-
"fmt"
|
|
5
|
-
|
|
6
|
-
"github.com/nexoral/axiodb-cli/pkg/protocol"
|
|
7
|
-
)
|
|
8
|
-
|
|
9
|
-
func CreateIndex(client *protocol.Client, dbName, collectionName string, fieldNames []string) (*protocol.Response, error) {
|
|
10
|
-
resp, err := client.Send("CREATE_INDEX", map[string]interface{}{
|
|
11
|
-
"dbName": dbName,
|
|
12
|
-
"collectionName": collectionName,
|
|
13
|
-
"fieldNames": fieldNames,
|
|
14
|
-
})
|
|
15
|
-
if err != nil {
|
|
16
|
-
return nil, fmt.Errorf("create index: %w", err)
|
|
17
|
-
}
|
|
18
|
-
if resp.StatusCode >= 400 {
|
|
19
|
-
return nil, fmt.Errorf("create index failed: %s", resp.Error)
|
|
20
|
-
}
|
|
21
|
-
return resp, nil
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
func DropIndex(client *protocol.Client, dbName, collectionName, indexName string) (*protocol.Response, error) {
|
|
25
|
-
resp, err := client.Send("DROP_INDEX", map[string]interface{}{
|
|
26
|
-
"dbName": dbName,
|
|
27
|
-
"collectionName": collectionName,
|
|
28
|
-
"indexName": indexName,
|
|
29
|
-
})
|
|
30
|
-
if err != nil {
|
|
31
|
-
return nil, fmt.Errorf("drop index: %w", err)
|
|
32
|
-
}
|
|
33
|
-
if resp.StatusCode >= 400 {
|
|
34
|
-
return nil, fmt.Errorf("drop index failed: %s", resp.Error)
|
|
35
|
-
}
|
|
36
|
-
return resp, nil
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
func ListIndexes(client *protocol.Client, dbName, collectionName string) (*protocol.Response, error) {
|
|
40
|
-
resp, err := client.Send("LIST_INDEXES", map[string]interface{}{
|
|
41
|
-
"dbName": dbName,
|
|
42
|
-
"collectionName": collectionName,
|
|
43
|
-
})
|
|
44
|
-
if err != nil {
|
|
45
|
-
return nil, fmt.Errorf("list indexes: %w", err)
|
|
46
|
-
}
|
|
47
|
-
if resp.StatusCode >= 400 {
|
|
48
|
-
return nil, fmt.Errorf("list indexes failed: %s", resp.Error)
|
|
49
|
-
}
|
|
50
|
-
return resp, nil
|
|
51
|
-
}
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
package commands
|
|
2
|
-
|
|
3
|
-
import (
|
|
4
|
-
"fmt"
|
|
5
|
-
|
|
6
|
-
"github.com/nexoral/axiodb-cli/pkg/protocol"
|
|
7
|
-
)
|
|
8
|
-
|
|
9
|
-
type TransactionStep struct {
|
|
10
|
-
Operation string `json:"operation"`
|
|
11
|
-
Data interface{} `json:"data,omitempty"`
|
|
12
|
-
Documents interface{} `json:"documents,omitempty"`
|
|
13
|
-
Query interface{} `json:"query,omitempty"`
|
|
14
|
-
UpdateData interface{} `json:"updateData,omitempty"`
|
|
15
|
-
ID string `json:"id,omitempty"`
|
|
16
|
-
IDs []string `json:"ids,omitempty"`
|
|
17
|
-
SavepointName string `json:"savepointName,omitempty"`
|
|
18
|
-
UpdateOne bool `json:"updateOne,omitempty"`
|
|
19
|
-
DeleteOne bool `json:"deleteOne,omitempty"`
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
func BeginTransaction(client *protocol.Client, dbName, collectionName string) (*protocol.Response, error) {
|
|
23
|
-
return client.Send("BEGIN_TRANSACTION", map[string]interface{}{"dbName": dbName, "collectionName": collectionName})
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
func CommitTransaction(client *protocol.Client, transactionID string) (*protocol.Response, error) {
|
|
27
|
-
return client.Send("COMMIT_TRANSACTION", map[string]interface{}{"transactionId": transactionID})
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
func RollbackTransaction(client *protocol.Client, transactionID string) (*protocol.Response, error) {
|
|
31
|
-
return client.Send("ROLLBACK_TRANSACTION", map[string]interface{}{"transactionId": transactionID})
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
func Savepoint(client *protocol.Client, transactionID, savepointName string) (*protocol.Response, error) {
|
|
35
|
-
return client.Send("SAVEPOINT", map[string]interface{}{"transactionId": transactionID, "savepointName": savepointName})
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
func RollbackToSavepoint(client *protocol.Client, transactionID, savepointName string) (*protocol.Response, error) {
|
|
39
|
-
return client.Send("ROLLBACK_TO_SAVEPOINT", map[string]interface{}{"transactionId": transactionID, "savepointName": savepointName})
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
func ReleaseSavepoint(client *protocol.Client, transactionID, savepointName string) (*protocol.Response, error) {
|
|
43
|
-
return client.Send("RELEASE_SAVEPOINT", map[string]interface{}{"transactionId": transactionID, "savepointName": savepointName})
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
func RunTransaction(client *protocol.Client, dbName, collectionName string, steps []TransactionStep) (*protocol.Response, error) {
|
|
47
|
-
begin, err := BeginTransaction(client, dbName, collectionName)
|
|
48
|
-
if err != nil || begin.StatusCode >= 400 {
|
|
49
|
-
if err != nil { return nil, fmt.Errorf("begin transaction: %w", err) }
|
|
50
|
-
return nil, fmt.Errorf("begin transaction failed: %s", begin.Error)
|
|
51
|
-
}
|
|
52
|
-
transactionID, ok := begin.Data.(map[string]interface{})["transactionId"].(string)
|
|
53
|
-
if !ok || transactionID == "" {
|
|
54
|
-
return nil, fmt.Errorf("begin transaction returned no transaction ID")
|
|
55
|
-
}
|
|
56
|
-
base := map[string]interface{}{"dbName": dbName, "collectionName": collectionName, "transactionId": transactionID}
|
|
57
|
-
for _, step := range steps {
|
|
58
|
-
params := map[string]interface{}{}
|
|
59
|
-
for key, value := range base { params[key] = value }
|
|
60
|
-
switch step.Operation {
|
|
61
|
-
case "insert": params["data"] = step.Data
|
|
62
|
-
case "insert-many": params["documents"] = step.Documents
|
|
63
|
-
case "query": params["query"] = step.Query
|
|
64
|
-
case "find-by-ids": params["ids"] = step.IDs
|
|
65
|
-
case "update-by-id": params["id"], params["updateData"] = step.ID, step.UpdateData
|
|
66
|
-
case "update-by-query": params["query"], params["updateData"], params["updateOne"] = step.Query, step.UpdateData, step.UpdateOne
|
|
67
|
-
case "delete-by-id": params["id"] = step.ID
|
|
68
|
-
case "delete-by-query": params["query"], params["deleteOne"] = step.Query, step.DeleteOne
|
|
69
|
-
case "savepoint", "rollback-to-savepoint", "release-savepoint": params["savepointName"] = step.SavepointName
|
|
70
|
-
default: return nil, fmt.Errorf("unsupported transaction operation: %s", step.Operation)
|
|
71
|
-
}
|
|
72
|
-
command := map[string]string{"insert":"INSERT_DOCUMENT", "insert-many":"INSERT_MANY_DOCUMENTS", "query":"QUERY_DOCUMENTS", "find-by-ids":"FIND_BY_IDS", "update-by-id":"UPDATE_DOCUMENT_BY_ID", "update-by-query":"UPDATE_DOCUMENTS_BY_QUERY", "delete-by-id":"DELETE_DOCUMENT_BY_ID", "delete-by-query":"DELETE_DOCUMENTS_BY_QUERY", "savepoint":"SAVEPOINT", "rollback-to-savepoint":"ROLLBACK_TO_SAVEPOINT", "release-savepoint":"RELEASE_SAVEPOINT"}[step.Operation]
|
|
73
|
-
response, sendErr := client.Send(command, params)
|
|
74
|
-
if sendErr != nil || response.StatusCode >= 400 {
|
|
75
|
-
_, _ = RollbackTransaction(client, transactionID)
|
|
76
|
-
if sendErr != nil { return nil, fmt.Errorf("transaction %s: %w", step.Operation, sendErr) }
|
|
77
|
-
return nil, fmt.Errorf("transaction %s failed: %s", step.Operation, response.Error)
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
commit, err := CommitTransaction(client, transactionID)
|
|
81
|
-
if err != nil { return nil, fmt.Errorf("commit transaction: %w", err) }
|
|
82
|
-
if commit.StatusCode >= 400 { return nil, fmt.Errorf("commit transaction failed: %s", commit.Error) }
|
|
83
|
-
return commit, nil
|
|
84
|
-
}
|
|
@@ -1,236 +0,0 @@
|
|
|
1
|
-
package httpclient
|
|
2
|
-
|
|
3
|
-
import (
|
|
4
|
-
"bytes"
|
|
5
|
-
"encoding/json"
|
|
6
|
-
"fmt"
|
|
7
|
-
"io"
|
|
8
|
-
"mime/multipart"
|
|
9
|
-
"net/http"
|
|
10
|
-
"net/http/cookiejar"
|
|
11
|
-
"net/url"
|
|
12
|
-
"os"
|
|
13
|
-
"path/filepath"
|
|
14
|
-
"strings"
|
|
15
|
-
"time"
|
|
16
|
-
)
|
|
17
|
-
|
|
18
|
-
type HTTPClient struct {
|
|
19
|
-
baseURL string
|
|
20
|
-
httpClient *http.Client
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
func (c *HTTPClient) doJSON(method, path string, payload interface{}) (map[string]interface{}, error) {
|
|
24
|
-
var body io.Reader
|
|
25
|
-
if payload != nil {
|
|
26
|
-
encoded, err := json.Marshal(payload)
|
|
27
|
-
if err != nil {
|
|
28
|
-
return nil, fmt.Errorf("encode request: %w", err)
|
|
29
|
-
}
|
|
30
|
-
body = bytes.NewReader(encoded)
|
|
31
|
-
}
|
|
32
|
-
req, err := http.NewRequest(method, c.baseURL+path, body)
|
|
33
|
-
if err != nil {
|
|
34
|
-
return nil, fmt.Errorf("create request: %w", err)
|
|
35
|
-
}
|
|
36
|
-
if payload != nil {
|
|
37
|
-
req.Header.Set("Content-Type", "application/json")
|
|
38
|
-
}
|
|
39
|
-
resp, err := c.httpClient.Do(req)
|
|
40
|
-
if err != nil {
|
|
41
|
-
return nil, fmt.Errorf("request failed: %w", err)
|
|
42
|
-
}
|
|
43
|
-
defer resp.Body.Close()
|
|
44
|
-
var result map[string]interface{}
|
|
45
|
-
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
|
|
46
|
-
return nil, fmt.Errorf("parse response: %w", err)
|
|
47
|
-
}
|
|
48
|
-
if resp.StatusCode >= 400 {
|
|
49
|
-
message, _ := result["message"].(string)
|
|
50
|
-
if message == "" {
|
|
51
|
-
message = resp.Status
|
|
52
|
-
}
|
|
53
|
-
return nil, fmt.Errorf("request failed: %s", message)
|
|
54
|
-
}
|
|
55
|
-
return result, nil
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
func (c *HTTPClient) ListUsers() (map[string]interface{}, error) {
|
|
59
|
-
return c.doJSON(http.MethodGet, "/api/auth/users/", nil)
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
func (c *HTTPClient) CreateUser(username, password, role string) (map[string]interface{}, error) {
|
|
63
|
-
return c.doJSON(http.MethodPost, "/api/auth/users/", map[string]string{"username": username, "password": password, "role": role})
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
func (c *HTTPClient) UpdateUserRole(username, role string) (map[string]interface{}, error) {
|
|
67
|
-
return c.doJSON(http.MethodPatch, "/api/auth/users/"+url.PathEscape(username)+"/role", map[string]string{"role": role})
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
func (c *HTTPClient) ResetUserPassword(username, password string) (map[string]interface{}, error) {
|
|
71
|
-
return c.doJSON(http.MethodPatch, "/api/auth/users/"+url.PathEscape(username)+"/reset-password", map[string]string{"newPassword": password})
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
func (c *HTTPClient) DeleteUser(username string) (map[string]interface{}, error) {
|
|
75
|
-
return c.doJSON(http.MethodDelete, "/api/auth/users/"+url.PathEscape(username), nil)
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
func (c *HTTPClient) ListRoles() (map[string]interface{}, error) {
|
|
79
|
-
return c.doJSON(http.MethodGet, "/api/auth/roles/", nil)
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
func (c *HTTPClient) CreateRole(roleName string, permissions []string) (map[string]interface{}, error) {
|
|
83
|
-
return c.doJSON(http.MethodPost, "/api/auth/roles/", map[string]interface{}{"roleName": roleName, "permissions": permissions})
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
func (c *HTTPClient) DeleteRole(roleName string) (map[string]interface{}, error) {
|
|
87
|
-
return c.doJSON(http.MethodDelete, "/api/auth/roles/"+url.PathEscape(roleName), nil)
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
func (c *HTTPClient) ListPermissions() (map[string]interface{}, error) {
|
|
91
|
-
return c.doJSON(http.MethodGet, "/api/auth/roles/permissions", nil)
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
func (c *HTTPClient) ChangeOwnPassword(currentPassword, newPassword string) (map[string]interface{}, error) {
|
|
95
|
-
return c.doJSON(http.MethodPatch, "/api/auth/change-password", map[string]string{"currentPassword": currentPassword, "newPassword": newPassword})
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
func New(host string, port int, timeout time.Duration) *HTTPClient {
|
|
99
|
-
jar, _ := cookiejar.New(nil)
|
|
100
|
-
return &HTTPClient{
|
|
101
|
-
baseURL: fmt.Sprintf("http://%s:%d", host, port),
|
|
102
|
-
httpClient: &http.Client{
|
|
103
|
-
Timeout: timeout,
|
|
104
|
-
Jar: jar,
|
|
105
|
-
},
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
func (c *HTTPClient) Login(username, password string) error {
|
|
110
|
-
body, _ := json.Marshal(map[string]string{
|
|
111
|
-
"username": username,
|
|
112
|
-
"password": password,
|
|
113
|
-
})
|
|
114
|
-
|
|
115
|
-
resp, err := c.httpClient.Post(c.baseURL+"/api/auth/login", "application/json", bytes.NewReader(body))
|
|
116
|
-
if err != nil {
|
|
117
|
-
return fmt.Errorf("login request failed: %w", err)
|
|
118
|
-
}
|
|
119
|
-
defer resp.Body.Close()
|
|
120
|
-
|
|
121
|
-
if resp.StatusCode == http.StatusOK {
|
|
122
|
-
return nil
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
var errResp struct {
|
|
126
|
-
Message string `json:"message"`
|
|
127
|
-
}
|
|
128
|
-
json.NewDecoder(resp.Body).Decode(&errResp)
|
|
129
|
-
msg := errResp.Message
|
|
130
|
-
if msg == "" {
|
|
131
|
-
msg = resp.Status
|
|
132
|
-
}
|
|
133
|
-
return fmt.Errorf("login failed: %s", msg)
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
func (c *HTTPClient) Logout() error {
|
|
137
|
-
resp, err := c.httpClient.Post(c.baseURL+"/api/auth/logout", "application/json", nil)
|
|
138
|
-
if err != nil {
|
|
139
|
-
return err
|
|
140
|
-
}
|
|
141
|
-
defer resp.Body.Close()
|
|
142
|
-
return nil
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
func (c *HTTPClient) Export(dbName string) (string, int64, error) {
|
|
146
|
-
url := fmt.Sprintf("%s/api/db/export-database/?dbName=%s", c.baseURL, dbName)
|
|
147
|
-
resp, err := c.httpClient.Get(url)
|
|
148
|
-
if err != nil {
|
|
149
|
-
return "", 0, fmt.Errorf("export request failed: %w", err)
|
|
150
|
-
}
|
|
151
|
-
defer resp.Body.Close()
|
|
152
|
-
|
|
153
|
-
if resp.StatusCode != http.StatusOK {
|
|
154
|
-
var errResp struct {
|
|
155
|
-
Message string `json:"message"`
|
|
156
|
-
}
|
|
157
|
-
json.NewDecoder(resp.Body).Decode(&errResp)
|
|
158
|
-
msg := errResp.Message
|
|
159
|
-
if msg == "" {
|
|
160
|
-
msg = resp.Status
|
|
161
|
-
}
|
|
162
|
-
return "", 0, fmt.Errorf("export failed: %s", msg)
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
filename := dbName + ".tar.gz"
|
|
166
|
-
if cd := resp.Header.Get("Content-Disposition"); cd != "" {
|
|
167
|
-
if idx := strings.Index(cd, "filename="); idx >= 0 {
|
|
168
|
-
name := cd[idx+9:]
|
|
169
|
-
name = strings.Trim(name, "\"")
|
|
170
|
-
if name != "" {
|
|
171
|
-
filename = filepath.Base(name)
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
out, err := os.Create(filename)
|
|
177
|
-
if err != nil {
|
|
178
|
-
return "", 0, fmt.Errorf("create file: %w", err)
|
|
179
|
-
}
|
|
180
|
-
defer out.Close()
|
|
181
|
-
|
|
182
|
-
written, err := io.Copy(out, resp.Body)
|
|
183
|
-
if err != nil {
|
|
184
|
-
os.Remove(filename)
|
|
185
|
-
return "", 0, fmt.Errorf("write file: %w", err)
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
return filename, written, nil
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
func (c *HTTPClient) Import(filePath string) (string, error) {
|
|
192
|
-
file, err := os.Open(filePath)
|
|
193
|
-
if err != nil {
|
|
194
|
-
return "", fmt.Errorf("open file: %w", err)
|
|
195
|
-
}
|
|
196
|
-
defer file.Close()
|
|
197
|
-
|
|
198
|
-
var body bytes.Buffer
|
|
199
|
-
writer := multipart.NewWriter(&body)
|
|
200
|
-
part, err := writer.CreateFormFile("file", filepath.Base(filePath))
|
|
201
|
-
if err != nil {
|
|
202
|
-
return "", fmt.Errorf("create form file: %w", err)
|
|
203
|
-
}
|
|
204
|
-
if _, err := io.Copy(part, file); err != nil {
|
|
205
|
-
return "", fmt.Errorf("write form data: %w", err)
|
|
206
|
-
}
|
|
207
|
-
writer.Close()
|
|
208
|
-
|
|
209
|
-
resp, err := c.httpClient.Post(
|
|
210
|
-
c.baseURL+"/api/db/import-database/",
|
|
211
|
-
writer.FormDataContentType(),
|
|
212
|
-
&body,
|
|
213
|
-
)
|
|
214
|
-
if err != nil {
|
|
215
|
-
return "", fmt.Errorf("import request failed: %w", err)
|
|
216
|
-
}
|
|
217
|
-
defer resp.Body.Close()
|
|
218
|
-
|
|
219
|
-
var result struct {
|
|
220
|
-
Message string `json:"message"`
|
|
221
|
-
Database string `json:"database"`
|
|
222
|
-
}
|
|
223
|
-
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
|
|
224
|
-
return "", fmt.Errorf("parse response: %w", err)
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
if resp.StatusCode != http.StatusOK {
|
|
228
|
-
msg := result.Message
|
|
229
|
-
if msg == "" {
|
|
230
|
-
msg = fmt.Sprintf("HTTP %d", resp.StatusCode)
|
|
231
|
-
}
|
|
232
|
-
return "", fmt.Errorf("import failed: %s", msg)
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
return result.Database, nil
|
|
236
|
-
}
|
package/cli/pkg/protocol/auth.go
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
package protocol
|
|
2
|
-
|
|
3
|
-
import "fmt"
|
|
4
|
-
|
|
5
|
-
type AuthResult struct {
|
|
6
|
-
Username string `json:"username"`
|
|
7
|
-
Role string `json:"role"`
|
|
8
|
-
MustChangePassword bool `json:"mustChangePassword"`
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
func Authenticate(client *Client, username, password string) (*AuthResult, error) {
|
|
12
|
-
resp, err := client.Send("AUTHENTICATE", map[string]interface{}{
|
|
13
|
-
"username": username,
|
|
14
|
-
"password": password,
|
|
15
|
-
})
|
|
16
|
-
if err != nil {
|
|
17
|
-
return nil, fmt.Errorf("authenticate: %w", err)
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
switch resp.StatusCode {
|
|
21
|
-
case 200:
|
|
22
|
-
data, ok := resp.Data.(map[string]interface{})
|
|
23
|
-
if !ok {
|
|
24
|
-
return nil, fmt.Errorf("unexpected auth response format")
|
|
25
|
-
}
|
|
26
|
-
result := &AuthResult{}
|
|
27
|
-
if v, ok := data["username"].(string); ok {
|
|
28
|
-
result.Username = v
|
|
29
|
-
}
|
|
30
|
-
if v, ok := data["role"].(string); ok {
|
|
31
|
-
result.Role = v
|
|
32
|
-
}
|
|
33
|
-
if v, ok := data["mustChangePassword"].(bool); ok {
|
|
34
|
-
result.MustChangePassword = v
|
|
35
|
-
}
|
|
36
|
-
return result, nil
|
|
37
|
-
case 401:
|
|
38
|
-
return nil, fmt.Errorf("authentication failed: invalid credentials")
|
|
39
|
-
case 403:
|
|
40
|
-
return nil, fmt.Errorf("authentication failed: password change required")
|
|
41
|
-
case 429:
|
|
42
|
-
return nil, fmt.Errorf("authentication failed: too many attempts, try again later")
|
|
43
|
-
default:
|
|
44
|
-
return nil, fmt.Errorf("authentication failed (status %d): %s", resp.StatusCode, resp.Error)
|
|
45
|
-
}
|
|
46
|
-
}
|