diff --git a/internal/gitsources/gitea/gitea.go b/internal/gitsources/gitea/gitea.go index b8939f31f..206971d09 100644 --- a/internal/gitsources/gitea/gitea.go +++ b/internal/gitsources/gitea/gitea.go @@ -18,6 +18,7 @@ package gitea import ( + "context" "crypto/tls" "fmt" "net" @@ -29,6 +30,7 @@ import ( "time" gitsource "github.com/sorintlab/agola/internal/gitsources" + "golang.org/x/oauth2" "code.gitea.io/sdk/gitea" "github.com/pkg/errors" @@ -41,14 +43,24 @@ const ( ClientNotFound = "404 Not Found" ) +var ( + // gitea corrently doesn't have any auth scope + GiteaOauth2Scopes = []string{""} +) + type Opts struct { - URL string - Token string - SkipVerify bool + URL string + Token string + SkipVerify bool + Oauth2ClientID string + Oauth2Secret string } type Client struct { - client *gitea.Client + client *gitea.Client + URL string + oauth2ClientID string + oauth2Secret string } // fromCommitStatus converts a gitsource commit status to a gitea commit status @@ -94,10 +106,47 @@ func New(opts Opts) (*Client, error) { client.SetHTTPClient(httpClient) return &Client{ - client: client, + client: client, + URL: opts.URL, + oauth2ClientID: opts.Oauth2ClientID, + oauth2Secret: opts.Oauth2Secret, }, nil } +func (c *Client) oauth2Config(callbackURL string) *oauth2.Config { + return &oauth2.Config{ + ClientID: c.oauth2ClientID, + ClientSecret: c.oauth2Secret, + Scopes: GiteaOauth2Scopes, + Endpoint: oauth2.Endpoint{ + AuthURL: fmt.Sprintf("%s/login/oauth/authorize", c.URL), + TokenURL: fmt.Sprintf("%s/login/oauth/access_token", c.URL), + }, + RedirectURL: callbackURL, + } +} + +func (c *Client) GetOauth2AuthorizationURL(callbackURL, state string) (string, error) { + var config = c.oauth2Config(callbackURL) + return config.AuthCodeURL(state), nil +} + +func (c *Client) RequestOauth2Token(callbackURL, code string) (*oauth2.Token, error) { + var config = c.oauth2Config(callbackURL) + token, err := config.Exchange(context.TODO(), code) + if err != nil { + return nil, errors.Wrapf(err, "cannot get oauth2 token") + } + return token, nil +} + +func (c *Client) RefreshOauth2Token(refreshToken string) (*oauth2.Token, error) { + var config = c.oauth2Config("") + token := &oauth2.Token{RefreshToken: refreshToken} + ts := config.TokenSource(context.TODO(), token) + return ts.Token() +} + func (c *Client) LoginPassword(username, password, tokenName string) (string, error) { // try to get agola access token if it already exists var accessToken string diff --git a/internal/services/gateway/common/gitsource.go b/internal/services/gateway/common/gitsource.go index 04a38ecd6..be0bf274e 100644 --- a/internal/services/gateway/common/gitsource.go +++ b/internal/services/gateway/common/gitsource.go @@ -28,9 +28,11 @@ import ( func newGitea(rs *types.RemoteSource, accessToken string) (*gitea.Client, error) { return gitea.New(gitea.Opts{ - URL: rs.APIURL, - SkipVerify: rs.SkipVerify, - Token: accessToken, + URL: rs.APIURL, + SkipVerify: rs.SkipVerify, + Token: accessToken, + Oauth2ClientID: rs.Oauth2ClientID, + Oauth2Secret: rs.Oauth2ClientSecret, }) } @@ -98,6 +100,8 @@ func GetOauth2Source(rs *types.RemoteSource, accessToken string) (gitsource.Oaut var oauth2Source gitsource.Oauth2Source var err error switch rs.Type { + case types.RemoteSourceTypeGitea: + oauth2Source, err = newGitea(rs, accessToken) case types.RemoteSourceTypeGitlab: oauth2Source, err = newGitlab(rs, accessToken) default: diff --git a/internal/services/types/types.go b/internal/services/types/types.go index 4daddaa05..f093957e5 100644 --- a/internal/services/types/types.go +++ b/internal/services/types/types.go @@ -171,7 +171,7 @@ type RemoteSource struct { func SourceSupportedAuthTypes(rsType RemoteSourceType) []RemoteSourceAuthType { switch rsType { case RemoteSourceTypeGitea: - return []RemoteSourceAuthType{RemoteSourceAuthTypePassword} + return []RemoteSourceAuthType{RemoteSourceAuthTypeOauth2, RemoteSourceAuthTypePassword} case RemoteSourceTypeGithub: fallthrough case RemoteSourceTypeGitlab: