mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2024-11-26 20:01:02 +00:00
Retrieve all user repo perms with a single API call (#3211)
This pull request addresses the issue https://github.com/woodpecker-ci/woodpecker/issues/3210. Ideally, the Bitbucket API should include repository permissions when utilizing the 'get all repositories' endpoint. However, as it currently does not provide this information, a viable solution is to fetch all permissions for every repository and then employ a dictionary to associate each repository with its respective permissions. Without implementing this fix, logging in becomes problematic for users with access to a substantial number of repositories (300+), as the process takes over 2 minutes to complete. --------- Co-authored-by: Alberto Alcón <albertoalcon@bit2me.com>
This commit is contained in:
parent
7b29d1da49
commit
07479dd645
4 changed files with 63 additions and 26 deletions
|
@ -203,6 +203,16 @@ func (c *config) Repos(ctx context.Context, u *model.User) ([]*model.Repo, error
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
userPermisions, err := client.ListPermissionsAll()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
userPermissionsByRepo := make(map[string]*internal.RepoPerm)
|
||||||
|
for _, permission := range userPermisions {
|
||||||
|
userPermissionsByRepo[permission.Repo.FullName] = permission
|
||||||
|
}
|
||||||
|
|
||||||
var all []*model.Repo
|
var all []*model.Repo
|
||||||
for _, workspace := range workspaces {
|
for _, workspace := range workspaces {
|
||||||
repos, err := client.ListReposAll(workspace.Slug)
|
repos, err := client.ListReposAll(workspace.Slug)
|
||||||
|
@ -210,14 +220,11 @@ func (c *config) Repos(ctx context.Context, u *model.User) ([]*model.Repo, error
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
for _, repo := range repos {
|
for _, repo := range repos {
|
||||||
perm, err := client.GetPermission(repo.FullName)
|
if perm, ok := userPermissionsByRepo[repo.FullName]; ok {
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
all = append(all, convertRepo(repo, perm))
|
all = append(all, convertRepo(repo, perm))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return all, nil
|
return all, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -185,21 +185,11 @@ func getUserRepos(c *gin.Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func permission(p string) string {
|
|
||||||
return fmt.Sprintf(permissionPayload, p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getPermissions(c *gin.Context) {
|
func getPermissions(c *gin.Context) {
|
||||||
query := c.Request.URL.Query()["q"][0]
|
if c.Query("page") == "" || c.Query("page") == "1" {
|
||||||
switch query {
|
c.String(200, permissionsPayLoad)
|
||||||
case `repository.full_name="test_name/permission_read"`:
|
} else {
|
||||||
c.String(200, permission("read"))
|
c.String(200, "{\"values\":[]}")
|
||||||
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"))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -367,14 +357,35 @@ const workspacesPayload = `
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
const permissionPayload = `
|
const permissionsPayLoad = `
|
||||||
{
|
{
|
||||||
"pagelen": 1,
|
"pagelen": 100,
|
||||||
|
"page": 1,
|
||||||
"values": [
|
"values": [
|
||||||
{
|
{
|
||||||
"permission": "%s"
|
"repository": {
|
||||||
|
"full_name": "test_name/repo_name"
|
||||||
|
},
|
||||||
|
"permission": "read"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"repository": {
|
||||||
|
"full_name": "test_name/permission_read"
|
||||||
|
},
|
||||||
|
"permission": "read"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"repository": {
|
||||||
|
"full_name": "test_name/permission_write"
|
||||||
|
},
|
||||||
|
"permission": "write"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"repository": {
|
||||||
|
"full_name": "test_name/permission_admin"
|
||||||
|
},
|
||||||
|
"permission": "admin"
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
"page": 1
|
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
|
@ -38,7 +38,8 @@ 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"
|
||||||
pathPermissions = "%s/2.0/user/permissions/repositories?q=repository.full_name=%q"
|
pathPermission = "%s/2.0/user/permissions/repositories?q=repository.full_name=%q"
|
||||||
|
pathPermissions = "%s/2.0/user/permissions/repositories?%s"
|
||||||
pathWorkspaces = "%s/2.0/workspaces/?%s"
|
pathWorkspaces = "%s/2.0/workspaces/?%s"
|
||||||
pathWorkspace = "%s/2.0/workspaces/%s"
|
pathWorkspace = "%s/2.0/workspaces/%s"
|
||||||
pathRepo = "%s/2.0/repositories/%s/%s"
|
pathRepo = "%s/2.0/repositories/%s/%s"
|
||||||
|
@ -161,7 +162,7 @@ func (c *Client) CreateStatus(owner, name, revision string, status *PipelineStat
|
||||||
|
|
||||||
func (c *Client) GetPermission(fullName string) (*RepoPerm, error) {
|
func (c *Client) GetPermission(fullName string) (*RepoPerm, error) {
|
||||||
out := new(RepoPermResp)
|
out := new(RepoPermResp)
|
||||||
uri := fmt.Sprintf(pathPermissions, c.base, fullName)
|
uri := fmt.Sprintf(pathPermission, c.base, fullName)
|
||||||
_, err := c.do(uri, get, nil, out)
|
_, err := c.do(uri, get, nil, out)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -173,6 +174,23 @@ func (c *Client) GetPermission(fullName string) (*RepoPerm, error) {
|
||||||
return out.Values[0], nil
|
return out.Values[0], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client) ListPermissions(opts *ListOpts) (*RepoPermResp, error) {
|
||||||
|
out := new(RepoPermResp)
|
||||||
|
uri := fmt.Sprintf(pathPermissions, c.base, opts.Encode())
|
||||||
|
_, err := c.do(uri, get, nil, out)
|
||||||
|
return out, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) ListPermissionsAll() ([]*RepoPerm, error) {
|
||||||
|
return shared_utils.Paginate(func(page int) ([]*RepoPerm, error) {
|
||||||
|
resp, err := c.ListPermissions(&ListOpts{Page: page, PageLen: 100})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return resp.Values, nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Client) ListBranches(owner, name string, opts *ListOpts) ([]*Branch, error) {
|
func (c *Client) ListBranches(owner, name string, opts *ListOpts) ([]*Branch, error) {
|
||||||
out := new(BranchResp)
|
out := new(BranchResp)
|
||||||
uri := fmt.Sprintf(pathBranches, c.base, owner, name, opts.Encode())
|
uri := fmt.Sprintf(pathBranches, c.base, owner, name, opts.Encode())
|
||||||
|
|
|
@ -254,6 +254,7 @@ type RepoPermResp struct {
|
||||||
|
|
||||||
type RepoPerm struct {
|
type RepoPerm struct {
|
||||||
Permission string `json:"permission"`
|
Permission string `json:"permission"`
|
||||||
|
Repo Repo `json:"repository"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type BranchResp struct {
|
type BranchResp struct {
|
||||||
|
|
Loading…
Reference in a new issue