package permissions import ( "bytes" "context" "encoding/json" "fmt" "io" "net/http" "net/url" "strings" "time" "github.com/labstack/echo/v4" "go.uber.org/zap" ) const defaultPermissionsURL = "https://permissions-api.hollow-a.sv15.metalkube.net" var defaultHTTPClient = &http.Client{ Timeout: 5 * time.Second, } type Client struct { logger *zap.SugaredLogger httpClient *http.Client token string baseURL *url.URL allowURL *url.URL } func (c *Client) Do(req *http.Request, out any) (*http.Response, error) { if c.token != "" { req.Header.Set(echo.HeaderAuthorization, "Bearer "+c.token) } req.Header.Set("Content-Type", "application/json") resp, err := c.httpClient.Do(req) if err != nil { return nil, err } if out != nil { defer resp.Body.Close() if err := json.NewDecoder(resp.Body).Decode(out); err != nil { return resp, err } } return resp, nil } func (c *Client) DoRequest(ctx context.Context, method, path string, body io.Reader, out any) (*http.Response, error) { path = strings.TrimPrefix(path, c.baseURL.Path) pathURL, err := url.Parse(path) if err != nil { return nil, err } url := c.baseURL.JoinPath(pathURL.Path) query := url.Query() for k, v := range pathURL.Query() { query[k] = v } url.RawQuery = query.Encode() req, err := http.NewRequestWithContext(ctx, method, url.String(), body) if err != nil { return nil, fmt.Errorf("failed to build request: %w", err) } resp, err := c.Do(req, out) if err != nil { return nil, fmt.Errorf("failed to get response: %w", err) } if resp.StatusCode < http.StatusOK || resp.StatusCode >= http.StatusMultipleChoices { return resp, fmt.Errorf("unexpected status code: %d", resp.StatusCode) } return resp, nil } func encodeJSON(v any) (*bytes.Buffer, error) { var buff bytes.Buffer if err := json.NewEncoder(&buff).Encode(v); err != nil { return nil, err } return &buff, nil } func NewClient(token string, options ...Option) (*Client, error) { client := &Client{ logger: zap.NewNop().Sugar(), httpClient: defaultHTTPClient, token: token, } for _, opt := range options { if err := opt(client); err != nil { return nil, err } } if client.baseURL == nil { uri, err := url.Parse(defaultPermissionsURL) if err != nil { return nil, err } client.baseURL = uri } client.allowURL = client.baseURL.JoinPath("/api/v1/allow") return client, nil }