Start working on specs implementation
This commit is contained in:
parent
2939e1356d
commit
2966d294fe
6 changed files with 125 additions and 63 deletions
|
@ -9,7 +9,7 @@ import (
|
|||
|
||||
"github.com/drone/drone/Godeps/_workspace/src/github.com/elazarl/go-bindata-assetfs"
|
||||
"github.com/drone/drone/pkg/config"
|
||||
"github.com/drone/drone/pkg/remote/builtin/github"
|
||||
"github.com/drone/drone/pkg/remote"
|
||||
"github.com/drone/drone/pkg/server"
|
||||
"github.com/drone/drone/pkg/server/session"
|
||||
|
||||
|
@ -49,7 +49,10 @@ func main() {
|
|||
panic(err)
|
||||
}
|
||||
|
||||
remote := github.New(settings)
|
||||
remote, err := remote.New(settings)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
session := session.New(settings)
|
||||
eventbus_ := eventbus.New()
|
||||
queue_ := queue.New()
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/drone/drone/Godeps/_workspace/src/github.com/naoina/toml"
|
||||
"github.com/drone/drone/Godeps/_workspace/src/github.com/vrischmann/envconfig"
|
||||
|
@ -9,12 +13,7 @@ import (
|
|||
|
||||
type Config struct {
|
||||
Remote struct {
|
||||
Kind string `envconfig:"optional"`
|
||||
Base string `envconfig:"optional"`
|
||||
Orgs []string `envconfig:"optional"`
|
||||
Open bool `envconfig:"optional"`
|
||||
Private bool `envconfig:"optional"`
|
||||
SkipVerify bool `envconfig:"optional"`
|
||||
Driver string `envconfig:"optional"`
|
||||
}
|
||||
|
||||
Auth struct {
|
||||
|
@ -67,20 +66,14 @@ type Config struct {
|
|||
Plugins []string `envconfig:"optional"`
|
||||
|
||||
Github struct {
|
||||
Client string `envconfig:"optional"`
|
||||
Secret string `envconfig:"optional"`
|
||||
Orgs []string `envconfig:"optional"`
|
||||
Open bool `envconfig:"optional"`
|
||||
}
|
||||
|
||||
GithubEnterprise struct {
|
||||
URL string `envconfig:"optional"`
|
||||
Client string `envconfig:"optional"`
|
||||
Secret string `envconfig:"optional"`
|
||||
Private bool `envconfig:"optional"`
|
||||
SkipVerify bool `envconfig:"optional"`
|
||||
Open bool `envconfig:"optional"`
|
||||
Orgs []string `envconfig:"optional"`
|
||||
API string `envconfig:"optional"`
|
||||
Host string `envconfig:"optional"`
|
||||
Client string `envconfig:"optional"`
|
||||
Secret string `envconfig:"optional"`
|
||||
PrivateMode bool `envconfig:"optional"`
|
||||
SkipVerify bool `envconfig:"optional"`
|
||||
Open bool `envconfig:"optional"`
|
||||
Orgs []string `envconfig:"optional"`
|
||||
}
|
||||
|
||||
Bitbucket struct {
|
||||
|
@ -132,5 +125,29 @@ func applyDefaults(c *Config) *Config {
|
|||
if len(c.Session.Secret) == 0 {
|
||||
c.Session.Secret = c.Auth.Secret
|
||||
}
|
||||
|
||||
// Prevent crash on start, use sqlite3
|
||||
// driver as default if DRONE_DATABASE_DRIVER and
|
||||
// DRONE_DATABASE_DATASOURCE not specifed
|
||||
if len(c.Database.Driver) == 0 && len(c.Database.Datasource) == 0 {
|
||||
c.Database.Driver = "sqlite3"
|
||||
|
||||
pwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
c.Database.Datasource = path.Join(pwd, "drone.sqlite3")
|
||||
}
|
||||
|
||||
// Set default settings for remotes
|
||||
switch strings.ToLower(c.Remote.Driver) {
|
||||
case "github":
|
||||
if len(c.Github.API) == 0 && len(c.Github.Host) == 0 {
|
||||
c.Github.API = "https://api.github.com/"
|
||||
c.Github.Host = "https://github.com"
|
||||
}
|
||||
}
|
||||
|
||||
return c
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package github
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
@ -10,14 +11,14 @@ import (
|
|||
|
||||
"github.com/drone/drone/Godeps/_workspace/src/github.com/hashicorp/golang-lru"
|
||||
"github.com/drone/drone/pkg/config"
|
||||
"github.com/drone/drone/pkg/oauth2"
|
||||
common "github.com/drone/drone/pkg/types"
|
||||
"github.com/drone/drone/pkg/utils/httputil"
|
||||
|
||||
"github.com/drone/drone/Godeps/_workspace/src/github.com/google/go-github/github"
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultAPI = "https://api.github.com/"
|
||||
DefaultURL = "https://github.com"
|
||||
DefaultScope = "repo,repo:status,user:email"
|
||||
)
|
||||
|
||||
|
@ -26,6 +27,8 @@ type GitHub struct {
|
|||
API string
|
||||
Client string
|
||||
Secret string
|
||||
AllowedOrgs []string
|
||||
Open bool
|
||||
PrivateMode bool
|
||||
SkipVerify bool
|
||||
|
||||
|
@ -34,12 +37,14 @@ type GitHub struct {
|
|||
|
||||
func New(conf *config.Config) *GitHub {
|
||||
var github = GitHub{
|
||||
API: DefaultAPI,
|
||||
URL: DefaultURL,
|
||||
Client: conf.Auth.Client,
|
||||
Secret: conf.Auth.Secret,
|
||||
PrivateMode: conf.Remote.Private,
|
||||
SkipVerify: conf.Remote.SkipVerify,
|
||||
API: conf.Github.API,
|
||||
URL: conf.Github.Host,
|
||||
Client: conf.Github.Client,
|
||||
Secret: conf.Github.Secret,
|
||||
AllowedOrgs: conf.Github.Orgs,
|
||||
Open: conf.Github.Open,
|
||||
PrivateMode: conf.Github.PrivateMode,
|
||||
SkipVerify: conf.Github.SkipVerify,
|
||||
}
|
||||
var err error
|
||||
github.cache, err = lru.New(1028)
|
||||
|
@ -47,12 +52,6 @@ func New(conf *config.Config) *GitHub {
|
|||
panic(err)
|
||||
}
|
||||
|
||||
// if GitHub enterprise then ensure we're using the
|
||||
// appropriate URLs
|
||||
if !strings.HasPrefix(conf.Remote.Base, DefaultURL) && len(conf.Remote.Base) != 0 {
|
||||
github.URL = conf.Remote.Base
|
||||
github.API = conf.Remote.Base + "/api/v3/"
|
||||
}
|
||||
// the API must have a trailing slash
|
||||
if !strings.HasSuffix(github.API, "/") {
|
||||
github.API += "/"
|
||||
|
@ -66,7 +65,7 @@ func New(conf *config.Config) *GitHub {
|
|||
|
||||
func (g *GitHub) Login(token, secret string) (*common.User, error) {
|
||||
client := NewClient(g.API, token, g.SkipVerify)
|
||||
login, err := GetUserEmail(client)
|
||||
login, err := GetUserEmail(client, g.URL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -92,6 +91,16 @@ func (g *GitHub) Orgs(u *common.User) ([]string, error) {
|
|||
return orgs_, nil
|
||||
}
|
||||
|
||||
// Accessor method, to allowed remote organizations field.
|
||||
func (g *GitHub) GetOrgs() []string {
|
||||
return g.AllowedOrgs
|
||||
}
|
||||
|
||||
// Accessor method, to open field.
|
||||
func (g *GitHub) GetOpen() bool {
|
||||
return g.Open
|
||||
}
|
||||
|
||||
// Repo fetches the named repository from the remote system.
|
||||
func (g *GitHub) Repo(u *common.User, owner, name string) (*common.Repo, error) {
|
||||
client := NewClient(g.API, u.Token, g.SkipVerify)
|
||||
|
@ -281,6 +290,25 @@ func (g *GitHub) push(r *http.Request) (*common.Hook, error) {
|
|||
return &common.Hook{Repo: repo, Commit: commit}, nil
|
||||
}
|
||||
|
||||
// ¯\_(ツ)_/¯
|
||||
func (g *GitHub) Oauth2Transport(r *http.Request) *oauth2.Transport {
|
||||
return &oauth2.Transport{
|
||||
Config: &oauth2.Config{
|
||||
ClientId: g.Client,
|
||||
ClientSecret: g.Secret,
|
||||
Scope: DefaultScope,
|
||||
AuthURL: fmt.Sprintf("%s/login/oauth/authorize", g.URL),
|
||||
TokenURL: fmt.Sprintf("%s/login/oauth/access_token", g.URL),
|
||||
RedirectURL: fmt.Sprintf("%s/authorize", httputil.GetURL(r)),
|
||||
//settings.Server.Scheme, settings.Server.Hostname),
|
||||
},
|
||||
Transport: &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: g.SkipVerify},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// pullRequest parses a hook with event type `pullRequest`
|
||||
// and returns the commit data.
|
||||
func (g *GitHub) pullRequest(r *http.Request) (*common.Hook, error) {
|
||||
|
|
|
@ -37,7 +37,7 @@ func NewClient(uri, token string, skipVerify bool) *github.Client {
|
|||
|
||||
// GetUserEmail is a heper function that retrieves the currently
|
||||
// authenticated user from GitHub + Email address.
|
||||
func GetUserEmail(client *github.Client) (*github.User, error) {
|
||||
func GetUserEmail(client *github.Client, defaultURL string) (*github.User, error) {
|
||||
user, _, err := client.Users.Get("")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -58,7 +58,7 @@ func GetUserEmail(client *github.Client) (*github.User, error) {
|
|||
// WARNING, HACK
|
||||
// for out-of-date github enterprise editions the primary
|
||||
// and verified fields won't exist.
|
||||
if !strings.HasPrefix(*user.HTMLURL, DefaultURL) && len(emails) != 0 {
|
||||
if !strings.HasPrefix(*user.HTMLURL, defaultURL) && len(emails) != 0 {
|
||||
user.Email = emails[0].Email
|
||||
return user, nil
|
||||
}
|
||||
|
|
|
@ -1,8 +1,14 @@
|
|||
package remote
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/drone/drone/pkg/config"
|
||||
"github.com/drone/drone/pkg/oauth2"
|
||||
"github.com/drone/drone/pkg/remote/builtin/github"
|
||||
common "github.com/drone/drone/pkg/types"
|
||||
)
|
||||
|
||||
|
@ -45,6 +51,27 @@ type Remote interface {
|
|||
// and returns the required data in a standard format.
|
||||
Hook(r *http.Request) (*common.Hook, error)
|
||||
|
||||
// Oauth2Transport
|
||||
Oauth2Transport(r *http.Request) *oauth2.Transport
|
||||
|
||||
// GetOrgs returns all allowed organizations for remote.
|
||||
GetOrgs() []string
|
||||
|
||||
// GetOpen returns boolean field with enabled or disabled
|
||||
// registration.
|
||||
GetOpen() bool
|
||||
|
||||
// Default scope for remote
|
||||
Scope() string
|
||||
}
|
||||
|
||||
func New(conf *config.Config) (Remote, error) {
|
||||
switch strings.ToLower(conf.Remote.Driver) {
|
||||
case "github":
|
||||
return github.New(conf), nil
|
||||
case "":
|
||||
return nil, errors.New("Remote not specifed, please set env variable DRONE_REMOTE_DRIVER")
|
||||
default:
|
||||
return nil, errors.New(fmt.Sprintf("Remote driver not supported: DRONE_REMOTE_DRIVER=%s", conf.Remote.Driver))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,13 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/drone/drone/Godeps/_workspace/src/github.com/gin-gonic/gin"
|
||||
"github.com/drone/drone/Godeps/_workspace/src/github.com/ungerik/go-gravatar"
|
||||
|
||||
log "github.com/drone/drone/Godeps/_workspace/src/github.com/Sirupsen/logrus"
|
||||
"github.com/drone/drone/pkg/oauth2"
|
||||
common "github.com/drone/drone/pkg/types"
|
||||
"github.com/drone/drone/pkg/utils/httputil"
|
||||
)
|
||||
|
||||
// GetLogin accepts a request to authorize the user and to
|
||||
|
@ -52,9 +48,9 @@ func GetLogin(c *gin.Context) {
|
|||
login := ToUser(c)
|
||||
|
||||
// check organization membership, if applicable
|
||||
if len(settings.Remote.Orgs) != 0 {
|
||||
if len(remote.GetOrgs()) != 0 {
|
||||
orgs, _ := remote.Orgs(login)
|
||||
if !checkMembership(orgs, settings.Remote.Orgs) {
|
||||
if !checkMembership(orgs, remote.GetOrgs()) {
|
||||
c.Redirect(303, "/login#error=access_denied_org")
|
||||
return
|
||||
}
|
||||
|
@ -73,7 +69,7 @@ func GetLogin(c *gin.Context) {
|
|||
// if self-registration is disabled we should
|
||||
// return a notAuthorized error. the only exception
|
||||
// is if no users exist yet in the system we'll proceed.
|
||||
if !settings.Remote.Open && count != 0 {
|
||||
if !remote.GetOpen() && count != 0 {
|
||||
log.Errorf("cannot register %s. registration closed", login.Login)
|
||||
c.Redirect(303, "/login#error=access_denied")
|
||||
return
|
||||
|
@ -131,35 +127,26 @@ func GetLogin(c *gin.Context) {
|
|||
// getLoginOauth2 is the default authorization implementation
|
||||
// using the oauth2 protocol.
|
||||
func getLoginOauth2(c *gin.Context) {
|
||||
var settings = ToSettings(c)
|
||||
var remote = ToRemote(c)
|
||||
|
||||
var scope = strings.Join(settings.Auth.Scope, ",")
|
||||
if scope == "" {
|
||||
scope = remote.Scope()
|
||||
}
|
||||
var config = &oauth2.Config{
|
||||
ClientId: settings.Auth.Client,
|
||||
ClientSecret: settings.Auth.Secret,
|
||||
Scope: scope,
|
||||
AuthURL: settings.Auth.Authorize,
|
||||
TokenURL: settings.Auth.AccessToken,
|
||||
RedirectURL: fmt.Sprintf("%s/authorize", httputil.GetURL(c.Request)),
|
||||
//settings.Server.Scheme, settings.Server.Hostname),
|
||||
}
|
||||
// Bugagazavr: I think this must be moved to remote config
|
||||
//var scope = strings.Join(settings.Auth.Scope, ",")
|
||||
//if scope == "" {
|
||||
// scope = remote.Scope()
|
||||
//}
|
||||
var transport = remote.Oauth2Transport(c.Request)
|
||||
|
||||
// get the OAuth code
|
||||
var code = c.Request.FormValue("code")
|
||||
//var state = c.Request.FormValue("state")
|
||||
if len(code) == 0 {
|
||||
// TODO this should be a random number, verified by a cookie
|
||||
c.Redirect(303, config.AuthCodeURL("random"))
|
||||
c.Redirect(303, transport.AuthCodeURL("random"))
|
||||
return
|
||||
}
|
||||
|
||||
// exhange for a token
|
||||
var trans = &oauth2.Transport{Config: config}
|
||||
var token, err = trans.Exchange(code)
|
||||
var token, err = transport.Exchange(code)
|
||||
if err != nil {
|
||||
log.Errorf("cannot get access_token. %s", err)
|
||||
c.Redirect(303, "/login#error=token_exchange")
|
||||
|
|
Loading…
Reference in a new issue