Merge pull request #2054 from bradrydzewski/feature/visibility

Add visibility field for access control
This commit is contained in:
Brad Rydzewski 2017-05-23 00:59:27 +02:00 committed by GitHub
commit 2341e09def
11 changed files with 135 additions and 71 deletions

View file

@ -25,3 +25,9 @@ const (
RepoFossil = "fossil" RepoFossil = "fossil"
RepoPerforce = "perforce" RepoPerforce = "perforce"
) )
const (
VisibilityPublic = "public"
VisibilityPrivate = "private"
VisibilityInternal = "internal"
)

View file

@ -22,6 +22,7 @@ type Repo struct {
Clone string `json:"clone_url,omitempty" meddler:"repo_clone"` Clone string `json:"clone_url,omitempty" meddler:"repo_clone"`
Branch string `json:"default_branch,omitempty" meddler:"repo_branch"` Branch string `json:"default_branch,omitempty" meddler:"repo_branch"`
Timeout int64 `json:"timeout,omitempty" meddler:"repo_timeout"` Timeout int64 `json:"timeout,omitempty" meddler:"repo_timeout"`
Visibility string `json:"visibility" meddler:"repo_visibility"`
IsPrivate bool `json:"private,omitempty" meddler:"repo_private"` IsPrivate bool `json:"private,omitempty" meddler:"repo_private"`
IsTrusted bool `json:"trusted" meddler:"repo_trusted"` IsTrusted bool `json:"trusted" meddler:"repo_trusted"`
IsStarred bool `json:"starred,omitempty" meddler:"-"` IsStarred bool `json:"starred,omitempty" meddler:"-"`
@ -40,6 +41,7 @@ type RepoPatch struct {
IsTrusted *bool `json:"trusted,omitempty"` IsTrusted *bool `json:"trusted,omitempty"`
IsGated *bool `json:"gated,omitempty"` IsGated *bool `json:"gated,omitempty"`
Timeout *int64 `json:"timeout,omitempty"` Timeout *int64 `json:"timeout,omitempty"`
Visibility *string `json:"visibility,omitempty"`
AllowPull *bool `json:"allow_pr,omitempty"` AllowPull *bool `json:"allow_pr,omitempty"`
AllowPush *bool `json:"allow_push,omitempty"` AllowPush *bool `json:"allow_push,omitempty"`
AllowDeploy *bool `json:"allow_deploy,omitempty"` AllowDeploy *bool `json:"allow_deploy,omitempty"`

View file

@ -2,7 +2,6 @@ package session
import ( import (
"net/http" "net/http"
"os"
"github.com/drone/drone/cache" "github.com/drone/drone/cache"
"github.com/drone/drone/model" "github.com/drone/drone/model"
@ -79,7 +78,6 @@ func Perm(c *gin.Context) *model.Perm {
} }
func SetPerm() gin.HandlerFunc { func SetPerm() gin.HandlerFunc {
PUBLIC_MODE := os.Getenv("PUBLIC_MODE")
return func(c *gin.Context) { return func(c *gin.Context) {
user := User(c) user := User(c)
@ -87,49 +85,24 @@ func SetPerm() gin.HandlerFunc {
perm := &model.Perm{} perm := &model.Perm{}
switch { switch {
// if the user is not authenticated, and the case user != nil && user.Admin:
// repository is private, the user has NO permission
// to view the repository.
case user == nil && repo.IsPrivate == true:
perm.Pull = false
perm.Push = false
perm.Admin = false
// if the user is not authenticated, but the repository
// is public, the user has pull-rights only.
case user == nil && repo.IsPrivate == false:
perm.Pull = true
perm.Push = false
perm.Admin = false
case user.Admin:
perm.Pull = true perm.Pull = true
perm.Push = true perm.Push = true
perm.Admin = true perm.Admin = true
// otherwise if the user is authenticated we should case user != nil:
// check the remote system to get the users permissiosn.
default:
var err error var err error
perm, err = cache.GetPerms(c, user, repo.Owner, repo.Name) perm, err = cache.GetPerms(c, user, repo.Owner, repo.Name)
if err != nil { if err != nil {
perm.Pull = false
perm.Push = false
perm.Admin = false
// debug
log.Errorf("Error fetching permission for %s %s", log.Errorf("Error fetching permission for %s %s",
user.Login, repo.FullName) user.Login, repo.FullName)
} }
// if we couldn't fetch permissions, but the repository
// is public, we should grant the user pull access.
if err != nil && repo.IsPrivate == false {
perm.Pull = true
}
} }
// all build logs are visible in public mode switch {
if PUBLIC_MODE != "" { case repo.Visibility == model.VisibilityPublic:
perm.Pull = true
case repo.Visibility == model.VisibilityInternal && user != nil:
perm.Pull = true perm.Pull = true
} }

View file

@ -1,44 +1,9 @@
package session package session
import ( import (
"os"
"testing" "testing"
"github.com/drone/drone/model"
"github.com/franela/goblin"
"github.com/gin-gonic/gin"
) )
func TestSetPerm(t *testing.T) { func TestSetPerm(t *testing.T) {
g := goblin.Goblin(t)
g.Describe("SetPerm", func() {
g.BeforeEach(func() {
os.Unsetenv("PUBLIC_MODE")
})
g.It("Should set pull to false (private repo, user not logged in)", func() {
c := gin.Context{}
c.Set("repo", &model.Repo{
IsPrivate: true,
})
SetPerm()(&c)
v, ok := c.Get("perm")
g.Assert(ok).IsTrue("perm was not set")
p, ok := v.(*model.Perm)
g.Assert(ok).IsTrue("perm was the wrong type")
g.Assert(p.Pull).IsFalse("pull should be false")
})
g.It("Should set pull to true (private repo, user not logged in, public mode)", func() {
os.Setenv("PUBLIC_MODE", "true")
c := gin.Context{}
c.Set("repo", &model.Repo{
IsPrivate: true,
})
SetPerm()(&c)
v, ok := c.Get("perm")
g.Assert(ok).IsTrue("perm was not set")
p, ok := v.(*model.Perm)
g.Assert(ok).IsTrue("perm was the wrong type")
g.Assert(p.Pull).IsTrue("pull should be true")
})
})
} }

View file

@ -55,11 +55,15 @@ func PostRepo(c *gin.Context) {
r.UserID = user.ID r.UserID = user.ID
r.AllowPush = true r.AllowPush = true
r.AllowPull = true r.AllowPull = true
r.Visibility = model.VisibilityPublic
r.Config = ".drone.yml" r.Config = ".drone.yml"
r.Timeout = 60 // 1 hour default build time r.Timeout = 60 // 1 hour default build time
r.Hash = base32.StdEncoding.EncodeToString( r.Hash = base32.StdEncoding.EncodeToString(
securecookie.GenerateRandomKey(32), securecookie.GenerateRandomKey(32),
) )
if r.IsPrivate {
r.Visibility = model.VisibilityPrivate
}
// crates the jwt token used to verify the repository // crates the jwt token used to verify the repository
t := token.New(token.HookToken, r.FullName) t := token.New(token.HookToken, r.FullName)
@ -132,6 +136,15 @@ func PatchRepo(c *gin.Context) {
if in.Config != nil { if in.Config != nil {
repo.Config = *in.Config repo.Config = *in.Config
} }
if in.Visibility != nil {
switch *in.Visibility {
case model.VisibilityInternal, model.VisibilityPrivate, model.VisibilityPublic:
repo.Visibility = *in.Visibility
default:
c.String(400, "Invalid visibility type")
return
}
}
err := store.UpdateRepo(c, repo) err := store.UpdateRepo(c, repo)
if err != nil { if err != nil {

View file

@ -88,6 +88,14 @@ var migrations = []struct {
name: "create-index-sender-repos", name: "create-index-sender-repos",
stmt: createIndexSenderRepos, stmt: createIndexSenderRepos,
}, },
{
name: "alter-table-add-repo-visibility",
stmt: alterTableAddRepoVisibility,
},
{
name: "update-table-set-repo-visibility",
stmt: updateTableSetRepoVisibility,
},
} }
// Migrate performs the database migration. If the migration fails // Migrate performs the database migration. If the migration fails
@ -442,3 +450,19 @@ CREATE TABLE IF NOT EXISTS senders (
var createIndexSenderRepos = ` var createIndexSenderRepos = `
CREATE INDEX sender_repo_ix ON senders (sender_repo_id); CREATE INDEX sender_repo_ix ON senders (sender_repo_id);
` `
//
// 013_add_column_repo_visibility.sql
//
var alterTableAddRepoVisibility = `
ALTER TABLE repos ADD COLUMN repo_visibility VARCHAR(50)
`
var updateTableSetRepoVisibility = `
UPDATE repos
SET repo_visibility = CASE
WHEN repo_private = 0 THEN 'public'
ELSE 'private'
END
`

View file

@ -0,0 +1,11 @@
-- name: alter-table-add-repo-visibility
ALTER TABLE repos ADD COLUMN repo_visibility VARCHAR(50)
-- name: update-table-set-repo-visibility
UPDATE repos
SET repo_visibility = CASE
WHEN repo_private = 0 THEN 'public'
ELSE 'private'
END

View file

@ -88,6 +88,14 @@ var migrations = []struct {
name: "create-index-sender-repos", name: "create-index-sender-repos",
stmt: createIndexSenderRepos, stmt: createIndexSenderRepos,
}, },
{
name: "alter-table-add-repo-visibility",
stmt: alterTableAddRepoVisibility,
},
{
name: "update-table-set-repo-visibility",
stmt: updateTableSetRepoVisibility,
},
} }
// Migrate performs the database migration. If the migration fails // Migrate performs the database migration. If the migration fails
@ -150,7 +158,7 @@ func selectCompleted(db *sql.DB) (map[string]struct{}, error) {
var migrationTableCreate = ` var migrationTableCreate = `
CREATE TABLE IF NOT EXISTS migrations ( CREATE TABLE IF NOT EXISTS migrations (
name VARCHAR(512) name VARCHAR(255)
,UNIQUE(name) ,UNIQUE(name)
) )
` `
@ -442,3 +450,19 @@ CREATE TABLE IF NOT EXISTS senders (
var createIndexSenderRepos = ` var createIndexSenderRepos = `
CREATE INDEX IF NOT EXISTS sender_repo_ix ON senders (sender_repo_id); CREATE INDEX IF NOT EXISTS sender_repo_ix ON senders (sender_repo_id);
` `
//
// 013_add_column_repo_visibility.sql
//
var alterTableAddRepoVisibility = `
ALTER TABLE repos ADD COLUMN repo_visibility VARCHAR(50)
`
var updateTableSetRepoVisibility = `
UPDATE repos
SET repo_visibility = (CASE
WHEN repo_private = true THEN 'public'
ELSE 'private'
END)
`

View file

@ -0,0 +1,11 @@
-- name: alter-table-add-repo-visibility
ALTER TABLE repos ADD COLUMN repo_visibility VARCHAR(50)
-- name: update-table-set-repo-visibility
UPDATE repos
SET repo_visibility = (CASE
WHEN repo_private = true THEN 'public'
ELSE 'private'
END)

View file

@ -92,6 +92,14 @@ var migrations = []struct {
name: "create-index-sender-repos", name: "create-index-sender-repos",
stmt: createIndexSenderRepos, stmt: createIndexSenderRepos,
}, },
{
name: "alter-table-add-repo-visibility",
stmt: alterTableAddRepoVisibility,
},
{
name: "update-table-set-repo-visibility",
stmt: updateTableSetRepoVisibility,
},
} }
// Migrate performs the database migration. If the migration fails // Migrate performs the database migration. If the migration fails
@ -154,7 +162,7 @@ func selectCompleted(db *sql.DB) (map[string]struct{}, error) {
var migrationTableCreate = ` var migrationTableCreate = `
CREATE TABLE IF NOT EXISTS migrations ( CREATE TABLE IF NOT EXISTS migrations (
name VARCHAR(512) name VARCHAR(255)
,UNIQUE(name) ,UNIQUE(name)
) )
` `
@ -443,3 +451,19 @@ CREATE TABLE IF NOT EXISTS senders (
var createIndexSenderRepos = ` var createIndexSenderRepos = `
CREATE INDEX IF NOT EXISTS sender_repo_ix ON senders (sender_repo_id); CREATE INDEX IF NOT EXISTS sender_repo_ix ON senders (sender_repo_id);
` `
//
// 013_add_column_repo_visibility.sql
//
var alterTableAddRepoVisibility = `
ALTER TABLE repos ADD COLUMN repo_visibility TEXT
`
var updateTableSetRepoVisibility = `
UPDATE repos
SET repo_visibility = CASE
WHEN repo_private = 0 THEN 'public'
ELSE 'private'
END
`

View file

@ -0,0 +1,11 @@
-- name: alter-table-add-repo-visibility
ALTER TABLE repos ADD COLUMN repo_visibility TEXT
-- name: update-table-set-repo-visibility
UPDATE repos
SET repo_visibility = CASE
WHEN repo_private = 0 THEN 'public'
ELSE 'private'
END