gitea: use custom http request for get tokens

Since the get tokens gitea api is used to do auth by username password we need
to know the api status code to detect if it's an unauthorized error (wrong
username/password) or another error.

Since the gitea client doesn't return the http response to inspect the status
code we'll use our own api call.
This commit is contained in:
Simone Gotti 2019-05-13 14:21:41 +02:00
parent 8331c43a18
commit a7ecfee795
2 changed files with 37 additions and 7 deletions

View File

@ -17,6 +17,8 @@ package gitea
import ( import (
"context" "context"
"crypto/tls" "crypto/tls"
"encoding/base64"
"encoding/json"
"fmt" "fmt"
"net" "net"
"net/http" "net/http"
@ -54,6 +56,7 @@ type Opts struct {
type Client struct { type Client struct {
client *gitea.Client client *gitea.Client
httpClient *http.Client
URL string URL string
oauth2ClientID string oauth2ClientID string
oauth2Secret string oauth2Secret string
@ -103,6 +106,7 @@ func New(opts Opts) (*Client, error) {
return &Client{ return &Client{
client: client, client: client,
httpClient: httpClient,
URL: opts.URL, URL: opts.URL,
oauth2ClientID: opts.Oauth2ClientID, oauth2ClientID: opts.Oauth2ClientID,
oauth2Secret: opts.Oauth2Secret, oauth2Secret: opts.Oauth2Secret,
@ -145,16 +149,39 @@ func (c *Client) RefreshOauth2Token(refreshToken string) (*oauth2.Token, error)
func (c *Client) LoginPassword(username, password, tokenName string) (string, error) { func (c *Client) LoginPassword(username, password, tokenName string) (string, error) {
// try to get agola access token if it already exists // try to get agola access token if it already exists
// use custom http call since gitea api client doesn't provide an easy way to
// guess if the username/password login failed
var accessToken string var accessToken string
tokens, err := c.client.ListAccessTokens(username, password)
if err == nil { tokens := make([]*gitea.AccessToken, 0, 10)
req, err := http.NewRequest("GET", c.URL+"/api/v1"+fmt.Sprintf("/users/%s/tokens", username), nil)
if err != nil {
return "", err
}
req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(username+":"+password)))
resp, err := c.httpClient.Do(req)
if err != nil {
return "", err
}
if resp.StatusCode == http.StatusUnauthorized {
return "", gitsource.ErrUnauthorized
}
if resp.StatusCode/100 != 2 {
return "", errors.Errorf("gitea api status code %d", resp.StatusCode)
}
defer resp.Body.Close()
dec := json.NewDecoder(resp.Body)
if err := dec.Decode(&tokens); err != nil {
return "", err
}
for _, token := range tokens { for _, token := range tokens {
if token.Name == tokenName { if token.Name == tokenName {
accessToken = token.Sha1 accessToken = token.Sha1
break break
} }
} }
}
// create access token // create access token
if accessToken == "" { if accessToken == "" {

View File

@ -15,6 +15,7 @@
package gitsource package gitsource
import ( import (
"errors"
"net/http" "net/http"
"github.com/sorintlab/agola/internal/services/types" "github.com/sorintlab/agola/internal/services/types"
@ -29,6 +30,8 @@ const (
CommitStatusFailed CommitStatus = "failed" CommitStatusFailed CommitStatus = "failed"
) )
var ErrUnauthorized = errors.New("unauthorized")
type GitSource interface { type GitSource interface {
GetRepoInfo(repopath string) (*RepoInfo, error) GetRepoInfo(repopath string) (*RepoInfo, error)
GetFile(repopath, commit, file string) ([]byte, error) GetFile(repopath, commit, file string) ([]byte, error)