mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2024-12-23 00:46:30 +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
|
||||
}
|
||||
|
||||
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
|
||||
for _, workspace := range workspaces {
|
||||
repos, err := client.ListReposAll(workspace.Slug)
|
||||
|
@ -210,12 +220,9 @@ func (c *config) Repos(ctx context.Context, u *model.User) ([]*model.Repo, error
|
|||
return nil, err
|
||||
}
|
||||
for _, repo := range repos {
|
||||
perm, err := client.GetPermission(repo.FullName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if perm, ok := userPermissionsByRepo[repo.FullName]; ok {
|
||||
all = append(all, convertRepo(repo, perm))
|
||||
}
|
||||
|
||||
all = append(all, convertRepo(repo, perm))
|
||||
}
|
||||
}
|
||||
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) {
|
||||
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"))
|
||||
if c.Query("page") == "" || c.Query("page") == "1" {
|
||||
c.String(200, permissionsPayLoad)
|
||||
} else {
|
||||
c.String(200, "{\"values\":[]}")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -367,14 +357,35 @@ const workspacesPayload = `
|
|||
}
|
||||
`
|
||||
|
||||
const permissionPayload = `
|
||||
const permissionsPayLoad = `
|
||||
{
|
||||
"pagelen": 1,
|
||||
"pagelen": 100,
|
||||
"page": 1,
|
||||
"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 (
|
||||
pathUser = "%s/2.0/user/"
|
||||
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"
|
||||
pathWorkspace = "%s/2.0/workspaces/%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) {
|
||||
out := new(RepoPermResp)
|
||||
uri := fmt.Sprintf(pathPermissions, c.base, fullName)
|
||||
uri := fmt.Sprintf(pathPermission, c.base, fullName)
|
||||
_, err := c.do(uri, get, nil, out)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -173,6 +174,23 @@ func (c *Client) GetPermission(fullName string) (*RepoPerm, error) {
|
|||
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) {
|
||||
out := new(BranchResp)
|
||||
uri := fmt.Sprintf(pathBranches, c.base, owner, name, opts.Encode())
|
||||
|
|
|
@ -254,6 +254,7 @@ type RepoPermResp struct {
|
|||
|
||||
type RepoPerm struct {
|
||||
Permission string `json:"permission"`
|
||||
Repo Repo `json:"repository"`
|
||||
}
|
||||
|
||||
type BranchResp struct {
|
||||
|
|
Loading…
Reference in a new issue