Merge pull request #2409 from folex/master

Use proper Bitbucket API for permission detection
This commit is contained in:
Brad Rydzewski 2018-04-30 09:48:18 -07:00 committed by GitHub
commit c01a05def6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 128 additions and 19 deletions

1
.gitignore vendored
View file

@ -7,3 +7,4 @@ extras/
release/ release/
server/swagger/files/*.json server/swagger/files/*.json
.idea/

View file

@ -176,17 +176,27 @@ func (c *config) Perm(u *model.User, owner, name string) (*model.Perm, error) {
client := c.newClient(u) client := c.newClient(u)
perms := new(model.Perm) perms := new(model.Perm)
_, err := client.FindRepo(owner, name) repo, err := client.FindRepo(owner, name)
if err != nil { if err != nil {
return perms, err return perms, err
} }
_, err = client.ListHooks(owner, name, &internal.ListOpts{}) perm, err := client.GetPermission(repo.FullName)
if err == nil { if err != nil {
perms.Push = true return perms, err
perms.Admin = true
} }
perms.Pull = true
switch perm.Permission {
case "admin":
perms.Admin = true
fallthrough
case "write":
perms.Push = true
fallthrough
default:
perms.Pull = true
}
return perms, nil return perms, nil
} }

View file

@ -161,19 +161,30 @@ func Test_bitbucket(t *testing.T) {
g.It("Should authorize read access", func() { g.It("Should authorize read access", func() {
perm, err := c.Perm( perm, err := c.Perm(
fakeUser, fakeUser,
fakeRepoNoHooks.Owner, fakeRepoReadOnly.Owner,
fakeRepoNoHooks.Name, fakeRepoReadOnly.Name,
) )
g.Assert(err == nil).IsTrue() g.Assert(err == nil).IsTrue()
g.Assert(perm.Pull).IsTrue() g.Assert(perm.Pull).IsTrue()
g.Assert(perm.Push).IsFalse() g.Assert(perm.Push).IsFalse()
g.Assert(perm.Admin).IsFalse() g.Assert(perm.Admin).IsFalse()
}) })
g.It("Should authorize write access", func() {
perm, err := c.Perm(
fakeUser,
fakeRepoWriteOnly.Owner,
fakeRepoWriteOnly.Name,
)
g.Assert(err == nil).IsTrue()
g.Assert(perm.Pull).IsTrue()
g.Assert(perm.Push).IsTrue()
g.Assert(perm.Admin).IsFalse()
})
g.It("Should authorize admin access", func() { g.It("Should authorize admin access", func() {
perm, err := c.Perm( perm, err := c.Perm(
fakeUser, fakeUser,
fakeRepo.Owner, fakeRepoAdmin.Owner,
fakeRepo.Name, fakeRepoAdmin.Name,
) )
g.Assert(err == nil).IsTrue() g.Assert(err == nil).IsTrue()
g.Assert(perm.Pull).IsTrue() g.Assert(perm.Pull).IsTrue()
@ -350,6 +361,24 @@ var (
FullName: "test_name/hook_empty", FullName: "test_name/hook_empty",
} }
fakeRepoReadOnly = &model.Repo{
Owner: "test_name",
Name: "permission_read",
FullName: "test_name/permission_read",
}
fakeRepoWriteOnly = &model.Repo{
Owner: "test_name",
Name: "permission_write",
FullName: "test_name/permission_write",
}
fakeRepoAdmin = &model.Repo{
Owner: "test_name",
Name: "permission_admin",
FullName: "test_name/permission_admin",
}
fakeBuild = &model.Build{ fakeBuild = &model.Build{
Commit: "9ecad50", Commit: "9ecad50",
} }

View file

@ -15,6 +15,7 @@
package fixtures package fixtures
import ( import (
"fmt"
"net/http" "net/http"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
@ -36,6 +37,7 @@ func Handler() http.Handler {
e.GET("/2.0/repositories/:owner", getUserRepos) e.GET("/2.0/repositories/:owner", getUserRepos)
e.GET("/2.0/teams/", getUserTeams) e.GET("/2.0/teams/", getUserTeams)
e.GET("/2.0/user/", getUser) e.GET("/2.0/user/", getUser)
e.GET("/2.0/user/permissions/repositories", getPermissions)
return e return e
} }
@ -70,6 +72,8 @@ func getRepo(c *gin.Context) {
switch c.Param("name") { switch c.Param("name") {
case "not_found", "repo_unknown", "repo_not_found": case "not_found", "repo_unknown", "repo_not_found":
c.String(404, "") c.String(404, "")
case "permission_read", "permission_write", "permission_admin":
c.String(200, fmt.Sprintf(permissionRepoPayload, c.Param("name")))
default: default:
c.String(200, repoPayload) c.String(200, repoPayload)
} }
@ -144,6 +148,24 @@ func getUserRepos(c *gin.Context) {
} }
} }
func permission(p string) string {
return fmt.Sprintf(permissionPayload, p)
}
func getPermissions(c *gin.Context) {
query := c.Request.URL.Query()["q"][0]
switch query {
case `repository.full_name="test_name/permission_read"`:
c.String(200, permission("read"))
case `repository.full_name="test_name/permission_write"`:
c.String(200, permission("write"))
case `repository.full_name="test_name/permission_admin"`:
c.String(200, permission("admin"))
default:
c.String(200, permission("read"))
}
}
const tokenPayload = ` const tokenPayload = `
{ {
"access_token":"2YotnFZFEjr1zCsicMWpAA", "access_token":"2YotnFZFEjr1zCsicMWpAA",
@ -170,6 +192,14 @@ const repoPayload = `
} }
` `
const permissionRepoPayload = `
{
"full_name": "test_name/%s",
"scm": "git",
"is_private": true
}
`
const repoHookPayload = ` const repoHookPayload = `
{ {
"pagelen": 10, "pagelen": 10,
@ -238,3 +268,15 @@ const userTeamPayload = `
] ]
} }
` `
const permissionPayload = `
{
"pagelen": 1,
"values": [
{
"permission": "%s"
}
],
"page": 1
}
`

View file

@ -34,15 +34,16 @@ const (
) )
const ( const (
pathUser = "%s/2.0/user/" pathUser = "%s/2.0/user/"
pathEmails = "%s/2.0/user/emails" pathEmails = "%s/2.0/user/emails"
pathTeams = "%s/2.0/teams/?%s" pathPermissions = "%s/2.0/user/permissions/repositories?q=repository.full_name=%q"
pathRepo = "%s/2.0/repositories/%s/%s" pathTeams = "%s/2.0/teams/?%s"
pathRepos = "%s/2.0/repositories/%s?%s" pathRepo = "%s/2.0/repositories/%s/%s"
pathHook = "%s/2.0/repositories/%s/%s/hooks/%s" pathRepos = "%s/2.0/repositories/%s?%s"
pathHooks = "%s/2.0/repositories/%s/%s/hooks?%s" pathHook = "%s/2.0/repositories/%s/%s/hooks/%s"
pathSource = "%s/1.0/repositories/%s/%s/src/%s/%s" pathHooks = "%s/2.0/repositories/%s/%s/hooks?%s"
pathStatus = "%s/2.0/repositories/%s/%s/commit/%s/statuses/build" pathSource = "%s/1.0/repositories/%s/%s/src/%s/%s"
pathStatus = "%s/2.0/repositories/%s/%s/commit/%s/statuses/build"
) )
type Client struct { type Client struct {
@ -152,6 +153,22 @@ func (c *Client) CreateStatus(owner, name, revision string, status *BuildStatus)
return c.do(uri, post, status, nil) return c.do(uri, post, status, nil)
} }
func (c *Client) GetPermission(fullName string) (*RepoPerm, error) {
out := new(RepoPermResp)
uri := fmt.Sprintf(pathPermissions, c.base, fullName)
err := c.do(uri, get, nil, out)
if err != nil {
return nil, err
}
if len(out.Values) == 0 {
return nil, fmt.Errorf("no permissions in repository %s", fullName)
} else {
return out.Values[0], nil
}
}
func (c *Client) do(rawurl, method string, in, out interface{}) error { func (c *Client) do(rawurl, method string, in, out interface{}) error {
uri, err := url.Parse(rawurl) uri, err := url.Parse(rawurl)

View file

@ -224,3 +224,13 @@ type Error struct {
func (e Error) Error() string { func (e Error) Error() string {
return e.Body.Message return e.Body.Message
} }
type RepoPermResp struct {
Page int `json:"page"`
Pages int `json:"pagelen"`
Values []*RepoPerm `json:"values"`
}
type RepoPerm struct {
Permission string `json:"permission"`
}