Files
zeromesh/sdk/api.go

211 lines
5.4 KiB
Go

package sdk
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
)
func (c *Client) doReq(method, path string, body, out interface{}) error {
url := strings.TrimRight(c.cfg.ControllerURL, "/") + path
var r io.Reader
if body != nil {
data, err := json.Marshal(body)
if err != nil {
return fmt.Errorf("marshal body: %w", err)
}
r = bytes.NewReader(data)
}
req, err := http.NewRequest(method, url, r)
if err != nil {
return fmt.Errorf("create request: %w", err)
}
if c.cfg.Token != "" {
req.Header.Set("Authorization", "Bearer "+c.cfg.Token)
}
if r != nil {
req.Header.Set("Content-Type", "application/json")
}
resp, err := c.httpc.Do(req)
if err != nil {
return fmt.Errorf("do request: %w", err)
}
defer resp.Body.Close()
respData, err := io.ReadAll(resp.Body)
if err != nil {
return fmt.Errorf("read response: %w", err)
}
if resp.StatusCode >= 400 {
var errResp struct{ Error string `json:"error"` }
if json.Unmarshal(respData, &errResp) == nil && errResp.Error != "" {
return fmt.Errorf("%s", errResp.Error)
}
return fmt.Errorf("HTTP %d: %s", resp.StatusCode, string(respData))
}
if out != nil {
if err := json.Unmarshal(respData, out); err != nil {
return fmt.Errorf("unmarshal response: %w", err)
}
}
return nil
}
func (c *Client) Login(username, password string) error {
var resp AuthResponse
if err := c.doReq("POST", "/api/v1/auth/login", map[string]string{
"username": username,
"password": password,
}, &resp); err != nil {
return err
}
c.cfg.Token = resp.Token
return nil
}
func (c *Client) Register(username, password string) (*User, error) {
var resp AuthResponse
if err := c.doReq("POST", "/api/v1/auth/register", map[string]string{
"username": username,
"password": password,
}, &resp); err != nil {
return nil, err
}
c.cfg.Token = resp.Token
return resp.User, nil
}
func (c *Client) InitAdmin(username, password string) (*User, error) {
var resp AuthResponse
if err := c.doReq("POST", "/api/v1/auth/init", map[string]string{
"username": username,
"password": password,
}, &resp); err != nil {
return nil, err
}
c.cfg.Token = resp.Token
return resp.User, nil
}
func (c *Client) CheckAdmin() (bool, error) {
var resp struct{ AdminExists bool `json:"admin_exists"` }
if err := c.doReq("GET", "/api/v1/admin/check", nil, &resp); err != nil {
return false, err
}
return resp.AdminExists, nil
}
func (c *Client) Dashboard() (*DashboardStats, error) {
var stats DashboardStats
if err := c.doReq("GET", "/api/v1/dashboard", nil, &stats); err != nil {
return nil, err
}
return &stats, nil
}
func (c *Client) AdminDashboard() (*DashboardStats, error) {
var stats DashboardStats
if err := c.doReq("GET", "/api/v1/admin/dashboard", nil, &stats); err != nil {
return nil, err
}
return &stats, nil
}
func (c *Client) Profile() (*ProfileResponse, error) {
var resp ProfileResponse
if err := c.doReq("GET", "/api/v1/user/profile", nil, &resp); err != nil {
return nil, err
}
return &resp, nil
}
func (c *Client) CreateNetwork(name, ipRange string) (*Network, error) {
body := map[string]string{"name": name}
if ipRange != "" {
body["ip_range"] = ipRange
}
var resp struct{ Network *Network `json:"network"` }
if err := c.doReq("POST", "/api/v1/network/create", body, &resp); err != nil {
return nil, err
}
return resp.Network, nil
}
func (c *Client) ListNetworks() ([]Network, error) {
var resp NetworkListResponse
if err := c.doReq("GET", "/api/v1/network/list", nil, &resp); err != nil {
return nil, err
}
return resp.Networks, nil
}
func (c *Client) GetNetwork(id uint32) (*Network, error) {
var resp struct{ Network *Network `json:"network"` }
if err := c.doReq("GET", fmt.Sprintf("/api/v1/network/%d", id), nil, &resp); err != nil {
return nil, err
}
return resp.Network, nil
}
func (c *Client) DeleteNetwork(id uint32) error {
return c.doReq("DELETE", fmt.Sprintf("/api/v1/network/%d", id), nil, nil)
}
func (c *Client) NetworkMembers(id uint32) ([]NetworkMember, error) {
var resp MembersResponse
if err := c.doReq("GET", fmt.Sprintf("/api/v1/network/%d/members", id), nil, &resp); err != nil {
return nil, err
}
return resp.Members, nil
}
func (c *Client) AuthorizeMember(networkID uint32, nodeID string) error {
return c.doReq("POST", fmt.Sprintf("/api/v1/network/%d/authorize", networkID),
map[string]string{"node_id": nodeID}, nil)
}
func (c *Client) DeauthorizeMember(networkID uint32, nodeID string) error {
return c.doReq("POST", fmt.Sprintf("/api/v1/network/%d/deauthorize", networkID),
map[string]string{"node_id": nodeID}, nil)
}
func (c *Client) RegisterNode(nodeID, publicKey, name, ipAddr string, port int, version string) (*Node, error) {
body := map[string]interface{}{
"node_id": nodeID,
"public_key": publicKey,
"name": name,
}
if ipAddr != "" {
body["ip_address"] = ipAddr
}
if port > 0 {
body["port"] = port
}
if version != "" {
body["version"] = version
}
var resp struct{ Node *Node `json:"node"` }
if err := c.doReq("POST", "/api/v1/node/register", body, &resp); err != nil {
return nil, err
}
return resp.Node, nil
}
func (c *Client) ListNodes() ([]Node, error) {
var resp NodeListResponse
if err := c.doReq("GET", "/api/v1/node/list", nil, &resp); err != nil {
return nil, err
}
return resp.Nodes, nil
}
func (c *Client) ListOnlineNodes() ([]Node, error) {
var resp NodeListResponse
if err := c.doReq("GET", "/api/v1/node/online", nil, &resp); err != nil {
return nil, err
}
return resp.Nodes, nil
}