Merge pull request #826 from mattbostock/per_plugin_registration

Per-remote open registration
This commit is contained in:
Brad Rydzewski
2015-01-16 22:04:51 -08:00
17 changed files with 52 additions and 122 deletions

View File

@@ -22,22 +22,11 @@ port=":80"
driver="sqlite3" driver="sqlite3"
datasource="/var/lib/drone/drone.sqlite" datasource="/var/lib/drone/drone.sqlite"
#####################################################################
# Open Registration allows users to self-register for Drone.
# This is recommended if Drone is being hosted behind a
# firewall.
#
# When false, the system admin will need to manually add
# users to Drone through the admin screens.
#
# [registration]
# open=true
# [github] # [github]
# client="" # client=""
# secret="" # secret=""
# orgs=[] # orgs=[]
# open=false
# [github_enterprise] # [github_enterprise]
# client="" # client=""
@@ -46,18 +35,22 @@ datasource="/var/lib/drone/drone.sqlite"
# url="" # url=""
# orgs=[] # orgs=[]
# private_mode=false # private_mode=false
# open=false
# [bitbucket] # [bitbucket]
# client="" # client=""
# secret="" # secret=""
# open=false
# [gitlab] # [gitlab]
# url="" # url=""
# skip_verify=false # skip_verify=false
# open=false
# [gogs] # [gogs]
# url="" # url=""
# secret="" # secret=""
# open=false
##################################################################### #####################################################################
# SMTP configuration for Drone. This is required if you plan # SMTP configuration for Drone. This is required if you plan

View File

@@ -27,19 +27,21 @@ type Bitbucket struct {
API string API string
Client string Client string
Secret string Secret string
Open bool
} }
func New(url, api, client, secret string) *Bitbucket { func New(url, api, client, secret string, open bool) *Bitbucket {
return &Bitbucket{ return &Bitbucket{
URL: url, URL: url,
API: api, API: api,
Client: client, Client: client,
Secret: secret, Secret: secret,
Open: open,
} }
} }
func NewDefault(client, secret string) *Bitbucket { func NewDefault(client, secret string, open bool) *Bitbucket {
return New(DefaultURL, DefaultAPI, client, secret) return New(DefaultURL, DefaultAPI, client, secret, open)
} }
// Authorize handles Bitbucket API Authorization // Authorize handles Bitbucket API Authorization
@@ -269,3 +271,7 @@ func (r *Bitbucket) ParseHook(req *http.Request) (*model.Hook, error) {
Message: hook.Commits[len(hook.Commits)-1].Message, Message: hook.Commits[len(hook.Commits)-1].Message,
}, nil }, nil
} }
func (r *Bitbucket) OpenRegistration() bool {
return r.Open
}

View File

@@ -9,6 +9,7 @@ var (
// Bitbucket cloud configuration details // Bitbucket cloud configuration details
bitbucketClient = config.String("bitbucket-client", "") bitbucketClient = config.String("bitbucket-client", "")
bitbucketSecret = config.String("bitbucket-secret", "") bitbucketSecret = config.String("bitbucket-secret", "")
bitbucketOpen = config.Bool("bitbucket-open", false)
) )
// Registers the Bitbucket plugin using the default // Registers the Bitbucket plugin using the default
@@ -19,6 +20,6 @@ func Register() {
return return
} }
remote.Register( remote.Register(
NewDefault(*bitbucketClient, *bitbucketSecret), NewDefault(*bitbucketClient, *bitbucketSecret, *bitbucketOpen),
) )
} }

View File

@@ -28,9 +28,10 @@ type GitHub struct {
Private bool Private bool
SkipVerify bool SkipVerify bool
Orgs []string Orgs []string
Open bool
} }
func New(url, api, client, secret string, private, skipVerify bool, orgs []string) *GitHub { func New(url, api, client, secret string, private, skipVerify bool, orgs []string, open bool) *GitHub {
var github = GitHub{ var github = GitHub{
URL: url, URL: url,
API: api, API: api,
@@ -39,6 +40,7 @@ func New(url, api, client, secret string, private, skipVerify bool, orgs []strin
Private: private, Private: private,
SkipVerify: skipVerify, SkipVerify: skipVerify,
Orgs: orgs, Orgs: orgs,
Open: open,
} }
// the API must have a trailing slash // the API must have a trailing slash
if !strings.HasSuffix(github.API, "/") { if !strings.HasSuffix(github.API, "/") {
@@ -51,8 +53,8 @@ func New(url, api, client, secret string, private, skipVerify bool, orgs []strin
return &github return &github
} }
func NewDefault(client, secret string, orgs []string) *GitHub { func NewDefault(client, secret string, orgs []string, open bool) *GitHub {
return New(DefaultURL, DefaultAPI, client, secret, false, false, orgs) return New(DefaultURL, DefaultAPI, client, secret, false, false, orgs, open)
} }
// Authorize handles GitHub API Authorization. // Authorize handles GitHub API Authorization.
@@ -305,3 +307,7 @@ func (r *GitHub) ParsePullRequestHook(req *http.Request) (*model.Hook, error) {
return &hook, nil return &hook, nil
} }
func (r *GitHub) OpenRegistration() bool {
return r.Open
}

View File

@@ -10,6 +10,7 @@ var (
githubClient = config.String("github-client", "") githubClient = config.String("github-client", "")
githubSecret = config.String("github-secret", "") githubSecret = config.String("github-secret", "")
githubOrgs = config.Strings("github-orgs") githubOrgs = config.Strings("github-orgs")
githubOpen = config.Bool("github-open", false)
// GitHub Enterprise configuration details // GitHub Enterprise configuration details
githubEnterpriseURL = config.String("github-enterprise-url", "") githubEnterpriseURL = config.String("github-enterprise-url", "")
@@ -19,6 +20,7 @@ var (
githubEnterprisePrivate = config.Bool("github-enterprise-private-mode", true) githubEnterprisePrivate = config.Bool("github-enterprise-private-mode", true)
githubEnterpriseSkipVerify = config.Bool("github-enterprise-skip-verify", false) githubEnterpriseSkipVerify = config.Bool("github-enterprise-skip-verify", false)
githubEnterpriseOrgs = config.Strings("github-enterprise-orgs") githubEnterpriseOrgs = config.Strings("github-enterprise-orgs")
githubEnterpriseOpen = config.Bool("github-enterprise-open", false)
) )
// Registers the GitHub plugins using the default // Registers the GitHub plugins using the default
@@ -35,7 +37,7 @@ func registerGitHub() {
return return
} }
remote.Register( remote.Register(
NewDefault(*githubClient, *githubSecret, *githubOrgs), NewDefault(*githubClient, *githubSecret, *githubOrgs, *githubOpen),
) )
} }
@@ -56,6 +58,7 @@ func registerGitHubEnterprise() {
*githubEnterprisePrivate, *githubEnterprisePrivate,
*githubEnterpriseSkipVerify, *githubEnterpriseSkipVerify,
*githubEnterpriseOrgs, *githubEnterpriseOrgs,
*githubEnterpriseOpen,
), ),
) )
} }

View File

@@ -13,12 +13,14 @@ import (
type Gitlab struct { type Gitlab struct {
url string url string
SkipVerify bool SkipVerify bool
Open bool
} }
func New(url string, skipVerify bool) *Gitlab { func New(url string, skipVerify, open bool) *Gitlab {
return &Gitlab{ return &Gitlab{
url: url, url: url,
SkipVerify: skipVerify, SkipVerify: skipVerify,
Open: open,
} }
} }
@@ -191,3 +193,7 @@ func (r *Gitlab) ParseHook(req *http.Request) (*model.Hook, error) {
return hook, nil return hook, nil
} }
func (r *Gitlab) OpenRegistration() bool {
return r.Open
}

View File

@@ -14,7 +14,7 @@ func Test_Github(t *testing.T) {
var server = testdata.NewServer() var server = testdata.NewServer()
defer server.Close() defer server.Close()
var gitlab = New(server.URL, false) var gitlab = New(server.URL, false, false)
var user = model.User{ var user = model.User{
Access: "e3b0c44298fc1c149afbf4c8996fb", Access: "e3b0c44298fc1c149afbf4c8996fb",
} }

View File

@@ -8,6 +8,7 @@ import (
var ( var (
gitlabURL = config.String("gitlab-url", "") gitlabURL = config.String("gitlab-url", "")
gitlabSkipVerify = config.Bool("gitlab-skip-verify", false) gitlabSkipVerify = config.Bool("gitlab-skip-verify", false)
gitlabOpen = config.Bool("gitlab-open", false)
) )
// Registers the Gitlab plugin using the default // Registers the Gitlab plugin using the default
@@ -21,6 +22,7 @@ func Register() {
New( New(
*gitlabURL, *gitlabURL,
*gitlabSkipVerify, *gitlabSkipVerify,
*gitlabOpen,
), ),
) )
} }

View File

@@ -16,10 +16,11 @@ import (
type Gogs struct { type Gogs struct {
URL string URL string
Secret string Secret string
Open bool
} }
func New(url string, secret string) *Gogs { func New(url string, secret string, open bool) *Gogs {
return &Gogs{URL: url, Secret: secret} return &Gogs{URL: url, Secret: secret, Open: open}
} }
// Authorize handles Gogs authorization // Authorize handles Gogs authorization
@@ -181,3 +182,7 @@ func (r *Gogs) ParseHook(req *http.Request) (*model.Hook, error) {
Message: payload.Commits[0].Message, Message: payload.Commits[0].Message,
}, nil }, nil
} }
func (r *Gogs) OpenRegistration() bool {
return r.Open
}

View File

@@ -8,6 +8,7 @@ import (
var ( var (
gogsUrl = config.String("gogs-url", "") gogsUrl = config.String("gogs-url", "")
gogsSecret = config.String("gogs-secret", "") gogsSecret = config.String("gogs-secret", "")
gogsOpen = config.Bool("gogs-open", false)
) )
// Registers the Gogs plugin using the default // Registers the Gogs plugin using the default
@@ -18,6 +19,6 @@ func Register() {
return return
} }
remote.Register( remote.Register(
New(*gogsUrl, *gogsSecret), New(*gogsUrl, *gogsSecret, *gogsOpen),
) )
} }

View File

@@ -32,6 +32,9 @@ type Remote interface {
// ParseHook parses the post-commit hook from the Request body // ParseHook parses the post-commit hook from the Request body
// and returns the required data in a standard format. // and returns the required data in a standard format.
ParseHook(r *http.Request) (*model.Hook, error) ParseHook(r *http.Request) (*model.Hook, error)
// Registration returns true if open registration is allowed
OpenRegistration() bool
} }
// List of registered plugins. // List of registered plugins.

View File

@@ -1,23 +0,0 @@
package capability
import (
"code.google.com/p/go.net/context"
)
type Capability map[string]bool
// Get the capability value from the map.
func (c Capability) Get(key string) bool {
return c[key]
}
// Sets the capability value in the map.
func (c Capability) Set(key string, value bool) {
c[key] = value
}
// Enabled returns true if the capability is
// enabled in the system.
func Enabled(c context.Context, key string) bool {
return FromContext(c).Get(key)
}

View File

@@ -1,24 +0,0 @@
package capability
import (
"testing"
"code.google.com/p/go.net/context"
"github.com/franela/goblin"
)
func TestBlobstore(t *testing.T) {
caps := map[string]bool{}
caps[Registration] = true
ctx := NewContext(context.Background(), caps)
g := goblin.Goblin(t)
g.Describe("Capabilities", func() {
g.It("Should get capabilities from context", func() {
g.Assert(Enabled(ctx, Registration)).Equal(true)
g.Assert(Enabled(ctx, "Fake Key")).Equal(false)
})
})
}

View File

@@ -1,5 +0,0 @@
package capability
const (
Registration = "REGISTRATION"
)

View File

@@ -1,32 +0,0 @@
package capability
import (
"code.google.com/p/go.net/context"
)
const reqkey = "capability"
// NewContext returns a Context whose Value method returns the
// application's Blobstore data.
func NewContext(parent context.Context, caps Capability) context.Context {
return &wrapper{parent, caps}
}
type wrapper struct {
context.Context
caps Capability
}
// Value returns the named key from the context.
func (c *wrapper) Value(key interface{}) interface{} {
if key == reqkey {
return c.caps
}
return c.Context.Value(key)
}
// FromContext returns the capability map for the
// current context.
func FromContext(c context.Context) Capability {
return c.Value(reqkey).(Capability)
}

View File

@@ -6,7 +6,6 @@ import (
"net/http" "net/http"
"github.com/drone/drone/plugin/remote" "github.com/drone/drone/plugin/remote"
"github.com/drone/drone/server/capability"
"github.com/drone/drone/server/datastore" "github.com/drone/drone/server/datastore"
"github.com/drone/drone/server/session" "github.com/drone/drone/server/session"
"github.com/drone/drone/server/sync" "github.com/drone/drone/server/sync"
@@ -49,7 +48,7 @@ func GetLogin(c web.C, w http.ResponseWriter, r *http.Request) {
// if self-registration is disabled we should // if self-registration is disabled we should
// return a notAuthorized error. the only exception // return a notAuthorized error. the only exception
// is if no users exist yet in the system we'll proceed. // is if no users exist yet in the system we'll proceed.
if capability.Enabled(ctx, capability.Registration) == false { if remote.OpenRegistration() == false {
users, err := datastore.GetUserList(ctx) users, err := datastore.GetUserList(ctx)
if err != nil || len(users) != 0 { if err != nil || len(users) != 0 {
log.Println("Unable to create account. Registration is closed") log.Println("Unable to create account. Registration is closed")

View File

@@ -26,7 +26,6 @@ import (
"github.com/drone/drone/plugin/remote/gitlab" "github.com/drone/drone/plugin/remote/gitlab"
"github.com/drone/drone/plugin/remote/gogs" "github.com/drone/drone/plugin/remote/gogs"
"github.com/drone/drone/server/blobstore" "github.com/drone/drone/server/blobstore"
"github.com/drone/drone/server/capability"
"github.com/drone/drone/server/datastore" "github.com/drone/drone/server/datastore"
"github.com/drone/drone/server/datastore/database" "github.com/drone/drone/server/datastore/database"
"github.com/drone/drone/server/worker/director" "github.com/drone/drone/server/worker/director"
@@ -56,10 +55,6 @@ var (
sslcrt = config.String("server-ssl-cert", "") sslcrt = config.String("server-ssl-cert", "")
sslkey = config.String("server-ssl-key", "") sslkey = config.String("server-ssl-key", "")
// Enable self-registration. When false, the system admin
// must grant user access.
open = config.Bool("registration-open", false)
workers *pool.Pool workers *pool.Pool
worker *director.Director worker *director.Director
pub *pubsub.PubSub pub *pubsub.PubSub
@@ -70,8 +65,6 @@ var (
nodes StringArr nodes StringArr
db *sql.DB db *sql.DB
caps map[string]bool
) )
func main() { func main() {
@@ -104,9 +97,6 @@ func main() {
gitlab.Register() gitlab.Register()
gogs.Register() gogs.Register()
caps = map[string]bool{}
caps[capability.Registration] = *open
// setup the database and cancel all pending // setup the database and cancel all pending
// commits in the system. // commits in the system.
db = database.MustConnect(*driver, *datasource) db = database.MustConnect(*driver, *datasource)
@@ -170,7 +160,6 @@ func ContextMiddleware(c *web.C, h http.Handler) http.Handler {
ctx = pool.NewContext(ctx, workers) ctx = pool.NewContext(ctx, workers)
ctx = director.NewContext(ctx, worker) ctx = director.NewContext(ctx, worker)
ctx = pubsub.NewContext(ctx, pub) ctx = pubsub.NewContext(ctx, pub)
ctx = capability.NewContext(ctx, caps)
// add the context to the goji web context // add the context to the goji web context
webcontext.Set(c, ctx) webcontext.Set(c, ctx)