diff --git a/auth.go b/auth.go index a22346a..d8d3c30 100644 --- a/auth.go +++ b/auth.go @@ -17,10 +17,33 @@ func WithAPIKey(apiKey string) ClientOption { currentTransport = http.DefaultTransport } - c.httpClient.Transport = &apiKeyTransport{ - apiKey: apiKey, + c.httpClient.Transport = &authHeaderTransport{ + name: "X-Api-Key", + value: apiKey, transport: currentTransport, } + + return nil + } +} + +func WithBearerToken(token string) ClientOption { + return func(c *Client) error { + if token == "" { + return fmt.Errorf("no token provided") + } + + currentTransport := c.httpClient.Transport + if currentTransport == nil { + currentTransport = http.DefaultTransport + } + + c.httpClient.Transport = &authHeaderTransport{ + name: "Authorization", + value: fmt.Sprintf("Bearer %s", token), + transport: currentTransport, + } + return nil } } @@ -35,12 +58,13 @@ func withoutAuth() requestOption { } } -type apiKeyTransport struct { - apiKey string +type authHeaderTransport struct { + name string + value string transport http.RoundTripper } -func (t apiKeyTransport) RoundTrip(req *http.Request) (*http.Response, error) { +func (t authHeaderTransport) RoundTrip(req *http.Request) (*http.Response, error) { unauthenticated, ok := req.Context().Value(contextKeyNoAuth).(bool) if ok && unauthenticated { return t.transport.RoundTrip(req) @@ -54,7 +78,7 @@ func (t apiKeyTransport) RoundTrip(req *http.Request) (*http.Response, error) { reqCopy.Header[hn] = append([]string(nil), hv...) } - reqCopy.Header.Set("X-Api-Key", t.apiKey) + reqCopy.Header.Set(t.name, t.value) return t.transport.RoundTrip(&reqCopy) } diff --git a/client.go b/client.go index 5bbd67d..80c9893 100644 --- a/client.go +++ b/client.go @@ -11,6 +11,7 @@ import ( "net/http/httputil" "net/url" "strconv" + "strings" "time" ) @@ -210,8 +211,17 @@ func (c Client) doRequest(req *http.Request, v interface{}) (*apiResponse, error } if v != nil { - if err = json.NewDecoder(res.Body).Decode(v); err != nil { - return nil, err + switch vt := v.(type) { + case *string: + if content, err := io.ReadAll(res.Body); err != nil { + return nil, err + } else { + *vt = strings.TrimSpace(string(content)) + } + default: + if err = json.NewDecoder(res.Body).Decode(v); err != nil { + return nil, err + } } } diff --git a/user.go b/user.go index 38babf0..84b1dfb 100644 --- a/user.go +++ b/user.go @@ -10,6 +10,27 @@ type UserService struct { client *Client } +func (u UserService) Login(ctx context.Context, username, password string) (string, error) { + body := url.Values{} + body.Set("username", username) + body.Set("password", password) + + req, err := u.client.newRequest(ctx, http.MethodPost, "/api/v1/user/login", withBody(body)) + if err != nil { + return "", err + } + + req.Header.Set("Accept", "*/*") + + var token string + _, err = u.client.doRequest(req, &token) + if err != nil { + return "", err + } + + return token, nil +} + func (u UserService) ForceChangePassword(ctx context.Context, username, password, newPassword string) error { body := url.Values{} body.Set("username", username)