diff --git a/bitbucket/internal/project_group_permission.go b/bitbucket/internal/project_group_permission.go new file mode 100644 index 00000000..4a4a4d74 --- /dev/null +++ b/bitbucket/internal/project_group_permission.go @@ -0,0 +1,150 @@ +package internal + +import ( + "context" + "fmt" + model "github.com/ctreminiom/go-atlassian/pkg/infra/models" + "github.com/ctreminiom/go-atlassian/service" + "github.com/ctreminiom/go-atlassian/service/bitbucket" + "net/http" +) + +type ProjectGroupPermission struct { + internalClient bitbucket.ProjectGroupPermissionConnector +} + +func (p *ProjectGroupPermission) Gets(ctx context.Context, workspace, projectKey string) (*model.BitbucketProjectGroupPermissionPageScheme, *model.ResponseScheme, error) { + return p.internalClient.Gets(ctx, workspace, projectKey) +} + +func (p *ProjectGroupPermission) Get(ctx context.Context, workspace, projectKey, groupSlug string) (*model.ProjectGroupPermissionScheme, *model.ResponseScheme, error) { + return p.internalClient.Get(ctx, workspace, projectKey, groupSlug) +} + +func (p *ProjectGroupPermission) Update(ctx context.Context, workspace, projectKey, groupSlug, permission string) (*model.ProjectGroupPermissionScheme, *model.ResponseScheme, error) { + return p.internalClient.Update(ctx, workspace, projectKey, groupSlug, permission) +} + +func (p *ProjectGroupPermission) Delete(ctx context.Context, workspace, projectKey, groupSlug string) (*model.ResponseScheme, error) { + return p.internalClient.Delete(ctx, workspace, projectKey, groupSlug) +} + +func NewProjectGroupPermissionService(client service.Connector) *ProjectGroupPermission { + return &ProjectGroupPermission{ + internalClient: &internalProjectGroupPermissionImpl{c: client}, + } +} + +type internalProjectGroupPermissionImpl struct { + c service.Connector +} + +func (i *internalProjectGroupPermissionImpl) Gets(ctx context.Context, workspace, projectKey string) (*model.BitbucketProjectGroupPermissionPageScheme, *model.ResponseScheme, error) { + + if workspace == "" { + return nil, nil, model.ErrNoWorkspace + } + + if projectKey == "" { + return nil, nil, model.ErrNoProjectSlug + } + + endpoint := fmt.Sprintf("2.0/workspaces/%s/projects/%s/permissions-config/groups", workspace, projectKey) + request, err := i.c.NewRequest(ctx, http.MethodGet, endpoint, "", nil) + if err != nil { + return nil, nil, err + } + + permissions := new(model.BitbucketProjectGroupPermissionPageScheme) + response, err := i.c.Call(request, permissions) + if err != nil { + return nil, response, err + } + + return permissions, response, nil +} + +func (i *internalProjectGroupPermissionImpl) Get(ctx context.Context, workspace, projectKey, groupSlug string) (*model.ProjectGroupPermissionScheme, *model.ResponseScheme, error) { + + if workspace == "" { + return nil, nil, model.ErrNoWorkspace + } + + if projectKey == "" { + return nil, nil, model.ErrNoProjectSlug + } + + if groupSlug == "" { + return nil, nil, model.ErrNoGroupSlug + } + + endpoint := fmt.Sprintf("2.0/workspaces/%s/projects/%s/permissions-config/groups/%s", workspace, projectKey, groupSlug) + request, err := i.c.NewRequest(ctx, http.MethodGet, endpoint, "", nil) + if err != nil { + return nil, nil, err + } + + permission := new(model.ProjectGroupPermissionScheme) + response, err := i.c.Call(request, permission) + if err != nil { + return nil, response, err + } + + return permission, response, nil +} + +func (i *internalProjectGroupPermissionImpl) Update(ctx context.Context, workspace, projectKey, groupSlug, permission string) (*model.ProjectGroupPermissionScheme, *model.ResponseScheme, error) { + + if workspace == "" { + return nil, nil, model.ErrNoWorkspace + } + + if projectKey == "" { + return nil, nil, model.ErrNoProjectSlug + } + + if groupSlug == "" { + return nil, nil, model.ErrNoGroupSlug + } + + if permission == "" { + return nil, nil, model.ErrNoPermissionSlug + } + + endpoint := fmt.Sprintf("2.0/workspaces/%s/projects/%s/permissions-config/groups/%s", workspace, projectKey, groupSlug) + request, err := i.c.NewRequest(ctx, http.MethodPut, endpoint, "", map[string]string{"permission": permission}) + if err != nil { + return nil, nil, err + } + + permissionUpdated := new(model.ProjectGroupPermissionScheme) + response, err := i.c.Call(request, permissionUpdated) + if err != nil { + return nil, response, err + } + + return permissionUpdated, response, nil +} + +func (i *internalProjectGroupPermissionImpl) Delete(ctx context.Context, workspace, projectKey, groupSlug string) (*model.ResponseScheme, error) { + + if workspace == "" { + return nil, model.ErrNoWorkspace + } + + if projectKey == "" { + return nil, model.ErrNoProjectSlug + } + + if groupSlug == "" { + return nil, model.ErrNoGroupSlug + } + + endpoint := fmt.Sprintf("2.0/workspaces/%s/projects/%s/permissions-config/groups/%s", workspace, projectKey, groupSlug) + request, err := i.c.NewRequest(ctx, http.MethodDelete, endpoint, "", nil) + if err != nil { + return nil, err + } + + return i.c.Call(request, nil) +} diff --git a/bitbucket/internal/project_impl.go b/bitbucket/internal/project_impl.go new file mode 100644 index 00000000..c965e23c --- /dev/null +++ b/bitbucket/internal/project_impl.go @@ -0,0 +1,121 @@ +package internal + +import ( + "context" + "fmt" + model "github.com/ctreminiom/go-atlassian/pkg/infra/models" + "github.com/ctreminiom/go-atlassian/service" + "github.com/ctreminiom/go-atlassian/service/bitbucket" + "net/http" +) + +// ProjectService handles communication with the project related methods of the Bitbucket API. +type ProjectService struct { + internalClient bitbucket.ProjectConnector +} + +// NewProjectService handles communication with the project related methods of the Bitbucket API. +func NewProjectService(client service.Connector) *ProjectService { + + return &ProjectService{ + internalClient: &internalProjectServiceImpl{c: client}, + } +} + +type internalProjectServiceImpl struct { + c service.Connector +} + +func (i *internalProjectServiceImpl) Create(ctx context.Context, workspace string, payload *model.BitbucketProjectScheme) (*model.BitbucketProjectScheme, *model.ResponseScheme, error) { + + if workspace == "" { + return nil, nil, model.ErrNoWorkspace + } + + endpoint := fmt.Sprintf("2.0/workspaces/%v/projects", workspace) + + request, err := i.c.NewRequest(ctx, http.MethodPost, endpoint, "", payload) + if err != nil { + return nil, nil, err + } + + projectCreated := new(model.BitbucketProjectScheme) + response, err := i.c.Call(request, projectCreated) + if err != nil { + return nil, response, err + } + + return projectCreated, response, nil +} + +func (i *internalProjectServiceImpl) Get(ctx context.Context, workspace, projectKey string) (*model.BitbucketProjectScheme, *model.ResponseScheme, error) { + + if workspace == "" { + return nil, nil, model.ErrNoWorkspace + } + + if projectKey == "" { + return nil, nil, model.ErrNoProjectSlug + } + + endpoint := fmt.Sprintf("2.0/workspaces/%v/projects/%v", workspace, projectKey) + + request, err := i.c.NewRequest(ctx, http.MethodGet, endpoint, "", nil) + if err != nil { + return nil, nil, err + } + + project := new(model.BitbucketProjectScheme) + response, err := i.c.Call(request, project) + if err != nil { + return nil, response, err + } + + return project, response, nil +} + +func (i *internalProjectServiceImpl) Update(ctx context.Context, workspace, projectKey string, payload *model.BitbucketProjectScheme) (*model.BitbucketProjectScheme, *model.ResponseScheme, error) { + + if workspace == "" { + return nil, nil, model.ErrNoWorkspace + } + + if projectKey == "" { + return nil, nil, model.ErrNoProjectSlug + } + + endpoint := fmt.Sprintf("2.0/workspaces/%v/projects/%v", workspace, projectKey) + + request, err := i.c.NewRequest(ctx, http.MethodPut, endpoint, "", payload) + if err != nil { + return nil, nil, err + } + + projectUpdated := new(model.BitbucketProjectScheme) + response, err := i.c.Call(request, projectUpdated) + if err != nil { + return nil, response, err + } + + return projectUpdated, response, nil +} + +func (i *internalProjectServiceImpl) Delete(ctx context.Context, workspace, projectKey string) (*model.ResponseScheme, error) { + + if workspace == "" { + return nil, model.ErrNoWorkspace + } + + if projectKey == "" { + return nil, model.ErrNoProjectSlug + } + + endpoint := fmt.Sprintf("2.0/workspaces/%v/projects/%v", workspace, projectKey) + + request, err := i.c.NewRequest(ctx, http.MethodDelete, endpoint, "", nil) + if err != nil { + return nil, err + } + + return i.c.Call(request, nil) +} diff --git a/bitbucket/internal/project_review_impl.go b/bitbucket/internal/project_review_impl.go new file mode 100644 index 00000000..2cc53794 --- /dev/null +++ b/bitbucket/internal/project_review_impl.go @@ -0,0 +1,149 @@ +package internal + +import ( + "context" + "fmt" + model "github.com/ctreminiom/go-atlassian/pkg/infra/models" + "github.com/ctreminiom/go-atlassian/service" + "github.com/ctreminiom/go-atlassian/service/bitbucket" + "net/http" +) + +type ProjectReviewService struct { + internalClient bitbucket.ProjectReviewerConnector +} + +func (p *ProjectReviewService) Gets(ctx context.Context, workspace, projectKey string) (*model.ProjectReviewerPageScheme, *model.ResponseScheme, error) { + return p.internalClient.Gets(ctx, workspace, projectKey) +} + +func (p *ProjectReviewService) Get(ctx context.Context, workspace, projectKey, userSlug string) (*model.ProjectReviewerScheme, *model.ResponseScheme, error) { + return p.internalClient.Get(ctx, workspace, projectKey, userSlug) +} + +func (p *ProjectReviewService) Add(ctx context.Context, workspace, projectKey, userSlug string) (*model.ProjectReviewerScheme, *model.ResponseScheme, error) { + return p.internalClient.Add(ctx, workspace, projectKey, userSlug) +} + +func (p *ProjectReviewService) Remove(ctx context.Context, workspace, projectKey, userSlug string) (*model.ResponseScheme, error) { + return p.internalClient.Remove(ctx, workspace, projectKey, userSlug) +} + +func NewProjectReviewService(client service.Connector) *ProjectReviewService { + return &ProjectReviewService{ + internalClient: &internalProjectServiceReviewerImpl{c: client}, + } +} + +type internalProjectServiceReviewerImpl struct { + c service.Connector +} + +func (i internalProjectServiceReviewerImpl) Gets(ctx context.Context, workspace, projectKey string) (*model.ProjectReviewerPageScheme, *model.ResponseScheme, error) { + + if workspace == "" { + return nil, nil, model.ErrNoWorkspace + } + + if projectKey == "" { + return nil, nil, model.ErrNoProjectSlug + } + + endpoint := fmt.Sprintf("2.0/workspaces/%s/projects/%s/default-reviewers", workspace, projectKey) + + request, err := i.c.NewRequest(ctx, http.MethodGet, endpoint, "", nil) + if err != nil { + return nil, nil, err + } + + reviewers := new(model.ProjectReviewerPageScheme) + response, err := i.c.Call(request, reviewers) + if err != nil { + return nil, response, err + } + + return reviewers, response, nil +} + +func (i internalProjectServiceReviewerImpl) Get(ctx context.Context, workspace, projectKey, userSlug string) (*model.ProjectReviewerScheme, *model.ResponseScheme, error) { + + if workspace == "" { + return nil, nil, model.ErrNoWorkspace + } + + if projectKey == "" { + return nil, nil, model.ErrNoProjectSlug + } + + if userSlug == "" { + return nil, nil, model.ErrNoAccountSlug + } + + endpoint := fmt.Sprintf("2.0/workspaces/%s/projects/%s/default-reviewers/%s", workspace, projectKey, userSlug) + request, err := i.c.NewRequest(ctx, http.MethodGet, endpoint, "", nil) + if err != nil { + return nil, nil, err + } + + reviewer := new(model.ProjectReviewerScheme) + response, err := i.c.Call(request, reviewer) + if err != nil { + return nil, response, err + } + + return reviewer, response, nil +} + +func (i internalProjectServiceReviewerImpl) Add(ctx context.Context, workspace, projectKey, userSlug string) (*model.ProjectReviewerScheme, *model.ResponseScheme, error) { + + if workspace == "" { + return nil, nil, model.ErrNoWorkspace + } + + if projectKey == "" { + return nil, nil, model.ErrNoProjectSlug + } + + if userSlug == "" { + return nil, nil, model.ErrNoAccountSlug + } + + endpoint := fmt.Sprintf("2.0/workspaces/%s/projects/%s/default-reviewers/%s", workspace, projectKey, userSlug) + + request, err := i.c.NewRequest(ctx, http.MethodPut, endpoint, "", nil) + if err != nil { + return nil, nil, err + } + + reviewer := new(model.ProjectReviewerScheme) + response, err := i.c.Call(request, reviewer) + if err != nil { + return nil, response, err + } + + return reviewer, response, nil +} + +func (i internalProjectServiceReviewerImpl) Remove(ctx context.Context, workspace, projectKey, userSlug string) (*model.ResponseScheme, error) { + + if workspace == "" { + return nil, model.ErrNoWorkspace + } + + if projectKey == "" { + return nil, model.ErrNoProjectSlug + } + + if userSlug == "" { + return nil, model.ErrNoAccountSlug + } + + endpoint := fmt.Sprintf("2.0/workspaces/%s/projects/%s/default-reviewers/%s", workspace, projectKey, userSlug) + + request, err := i.c.NewRequest(ctx, http.MethodDelete, endpoint, "", nil) + if err != nil { + return nil, err + } + + return i.c.Call(request, nil) +} diff --git a/bitbucket/internal/project_user_permission.go b/bitbucket/internal/project_user_permission.go new file mode 100644 index 00000000..8ac71233 --- /dev/null +++ b/bitbucket/internal/project_user_permission.go @@ -0,0 +1,150 @@ +package internal + +import ( + "context" + "fmt" + model "github.com/ctreminiom/go-atlassian/pkg/infra/models" + "github.com/ctreminiom/go-atlassian/service" + "github.com/ctreminiom/go-atlassian/service/bitbucket" + "net/http" +) + +type ProjectUserPermission struct { + internalClient bitbucket.ProjectUserPermissionConnector +} + +func (p *ProjectUserPermission) Gets(ctx context.Context, workspace, projectKey string) (*model.BitbucketProjectUserPermissionPageScheme, *model.ResponseScheme, error) { + return p.internalClient.Gets(ctx, workspace, projectKey) +} + +func (p *ProjectUserPermission) Get(ctx context.Context, workspace, projectKey, userSlug string) (*model.BitbucketProjectUserPermissionScheme, *model.ResponseScheme, error) { + return p.internalClient.Get(ctx, workspace, projectKey, userSlug) +} + +func (p *ProjectUserPermission) Update(ctx context.Context, workspace, projectKey, userSlug, permission string) (*model.BitbucketProjectUserPermissionScheme, *model.ResponseScheme, error) { + return p.internalClient.Update(ctx, workspace, projectKey, userSlug, permission) +} + +func (p *ProjectUserPermission) Delete(ctx context.Context, workspace, projectKey, userSlug string) (*model.ResponseScheme, error) { + return p.internalClient.Delete(ctx, workspace, projectKey, userSlug) +} + +func NewProjectUserPermissionService(client service.Connector) *ProjectUserPermission { + return &ProjectUserPermission{ + internalClient: &internalProjectUserPermissionImpl{c: client}, + } +} + +type internalProjectUserPermissionImpl struct { + c service.Connector +} + +func (i *internalProjectUserPermissionImpl) Gets(ctx context.Context, workspace, projectKey string) (*model.BitbucketProjectUserPermissionPageScheme, *model.ResponseScheme, error) { + + if workspace == "" { + return nil, nil, model.ErrNoWorkspace + } + + if projectKey == "" { + return nil, nil, model.ErrNoProjectSlug + } + + endpoint := fmt.Sprintf("2.0/workspaces/%s/projects/%s/permissions-config/users", workspace, projectKey) + request, err := i.c.NewRequest(ctx, http.MethodGet, endpoint, "", nil) + if err != nil { + return nil, nil, err + } + + permissions := new(model.BitbucketProjectUserPermissionPageScheme) + response, err := i.c.Call(request, permissions) + if err != nil { + return nil, response, err + } + + return permissions, response, nil +} + +func (i *internalProjectUserPermissionImpl) Get(ctx context.Context, workspace, projectKey, userSlug string) (*model.BitbucketProjectUserPermissionScheme, *model.ResponseScheme, error) { + + if workspace == "" { + return nil, nil, model.ErrNoWorkspace + } + + if projectKey == "" { + return nil, nil, model.ErrNoProjectSlug + } + + if userSlug == "" { + return nil, nil, model.ErrNoAccountSlug + } + + endpoint := fmt.Sprintf("2.0/workspaces/%s/projects/%s/permissions-config/users/%s", workspace, projectKey, userSlug) + request, err := i.c.NewRequest(ctx, http.MethodGet, endpoint, "", nil) + if err != nil { + return nil, nil, err + } + + permission := new(model.BitbucketProjectUserPermissionScheme) + response, err := i.c.Call(request, permission) + if err != nil { + return nil, response, err + } + + return permission, response, nil +} + +func (i *internalProjectUserPermissionImpl) Update(ctx context.Context, workspace, projectKey, userSlug, permission string) (*model.BitbucketProjectUserPermissionScheme, *model.ResponseScheme, error) { + + if workspace == "" { + return nil, nil, model.ErrNoWorkspace + } + + if projectKey == "" { + return nil, nil, model.ErrNoProjectSlug + } + + if userSlug == "" { + return nil, nil, model.ErrNoAccountSlug + } + + if permission == "" { + return nil, nil, model.ErrNoPermissionSlug + } + + endpoint := fmt.Sprintf("2.0/workspaces/%s/projects/%s/permissions-config/users/%s", workspace, projectKey, userSlug) + request, err := i.c.NewRequest(ctx, http.MethodPut, endpoint, "", map[string]string{"permission": permission}) + if err != nil { + return nil, nil, err + } + + permissionUpdated := new(model.BitbucketProjectUserPermissionScheme) + response, err := i.c.Call(request, permissionUpdated) + if err != nil { + return nil, response, err + } + + return permissionUpdated, response, nil +} + +func (i *internalProjectUserPermissionImpl) Delete(ctx context.Context, workspace, projectKey, userSlug string) (*model.ResponseScheme, error) { + + if workspace == "" { + return nil, model.ErrNoWorkspace + } + + if projectKey == "" { + return nil, model.ErrNoProjectSlug + } + + if userSlug == "" { + return nil, model.ErrNoAccountSlug + } + + endpoint := fmt.Sprintf("2.0/workspaces/%s/projects/%s/permissions-config/users/%s", workspace, projectKey, userSlug) + request, err := i.c.NewRequest(ctx, http.MethodDelete, endpoint, "", nil) + if err != nil { + return nil, err + } + + return i.c.Call(request, nil) +} diff --git a/bitbucket/internal/workspace_impl.go b/bitbucket/internal/workspace_impl.go index 13ea6c84..663bf81f 100644 --- a/bitbucket/internal/workspace_impl.go +++ b/bitbucket/internal/workspace_impl.go @@ -32,7 +32,7 @@ type WorkspaceService struct { // GET /2.0/workspaces/{workspace} // // https://docs.go-atlassian.io/bitbucket-cloud/workspace#get-a-workspace -func (w *WorkspaceService) Get(ctx context.Context, workspace string) (*model.WorkspaceScheme, *model.ResponseScheme, error) { +func (w *WorkspaceService) Get(ctx context.Context, workspace string) (*model.BitbucketWorkspaceScheme, *model.ResponseScheme, error) { return w.internalClient.Get(ctx, workspace) } @@ -70,7 +70,7 @@ type internalWorkspaceServiceImpl struct { } // Get returns the requested workspace. -func (i *internalWorkspaceServiceImpl) Get(ctx context.Context, workspace string) (*model.WorkspaceScheme, *model.ResponseScheme, error) { +func (i *internalWorkspaceServiceImpl) Get(ctx context.Context, workspace string) (*model.BitbucketWorkspaceScheme, *model.ResponseScheme, error) { if workspace == "" { return nil, nil, model.ErrNoWorkspace @@ -83,7 +83,7 @@ func (i *internalWorkspaceServiceImpl) Get(ctx context.Context, workspace string return nil, nil, err } - result := new(model.WorkspaceScheme) + result := new(model.BitbucketWorkspaceScheme) response, err := i.c.Call(request, result) if err != nil { return nil, response, err diff --git a/bitbucket/internal/workspace_impl_test.go b/bitbucket/internal/workspace_impl_test.go index db7837ad..6994284a 100644 --- a/bitbucket/internal/workspace_impl_test.go +++ b/bitbucket/internal/workspace_impl_test.go @@ -51,7 +51,7 @@ func Test_internalWorkspaceServiceImpl_Get(t *testing.T) { client.On("Call", &http.Request{}, - &model.WorkspaceScheme{}). + &model.BitbucketWorkspaceScheme{}). Return(&model.ResponseScheme{}, nil) fields.c = client diff --git a/pkg/infra/models/bitbucket_group.go b/pkg/infra/models/bitbucket_group.go new file mode 100644 index 00000000..02f48660 --- /dev/null +++ b/pkg/infra/models/bitbucket_group.go @@ -0,0 +1,17 @@ +package models + +// BitbucketGroupScheme represents a Bitbucket group. +type BitbucketGroupScheme struct { + Links *BitbucketGroupLinksScheme `json:"links"` + Owner *BitbucketAccountScheme `json:"owner"` + Workspace *BitbucketWorkspaceScheme `json:"workspace"` + Name string `json:"name"` + Slug string `json:"slug"` + FullSlug string `json:"full_slug"` +} + +// BitbucketGroupLinksScheme represents a collection of links related to a Bitbucket group. +type BitbucketGroupLinksScheme struct { + Self *BitbucketLinkScheme `json:"self,omitempty"` + HTML *BitbucketLinkScheme `json:"html,omitempty"` +} diff --git a/pkg/infra/models/bitbucket_project_group_permissions.go b/pkg/infra/models/bitbucket_project_group_permissions.go new file mode 100644 index 00000000..19303984 --- /dev/null +++ b/pkg/infra/models/bitbucket_project_group_permissions.go @@ -0,0 +1,22 @@ +package models + +type BitbucketProjectGroupPermissionPageScheme struct { + Size int `json:"size"` + Page int `json:"page"` + Pagelen int `json:"pagelen"` + Next string `json:"next"` + Previous string `json:"previous"` + Values []*ProjectGroupPermissionScheme `json:"values"` +} + +type ProjectGroupPermissionScheme struct { + Type string `json:"type"` + Links *ProjectGroupPermissionLinksScheme `json:"links"` + Permission string `json:"permission"` + Group *BitbucketGroupScheme `json:"group"` + Project *BitbucketProjectScheme `json:"project"` +} + +type ProjectGroupPermissionLinksScheme struct { + Self *BitbucketLinkScheme `json:"self,omitempty"` +} diff --git a/pkg/infra/models/bitbucket_project_reviewer.go b/pkg/infra/models/bitbucket_project_reviewer.go new file mode 100644 index 00000000..1e563788 --- /dev/null +++ b/pkg/infra/models/bitbucket_project_reviewer.go @@ -0,0 +1,16 @@ +package models + +type ProjectReviewerPageScheme struct { + Size int `json:"size,omitempty"` + Page int `json:"page,omitempty"` + Pagelen int `json:"pagelen,omitempty"` + Next string `json:"next,omitempty"` + Previous string `json:"previous,omitempty"` + Values []*ProjectReviewerScheme `json:"values,omitempty"` +} + +type ProjectReviewerScheme struct { + Type string `json:"type,omitempty"` + ReviewerType string `json:"reviewer_type,omitempty"` + User *BitbucketAccountScheme `json:"user,omitempty"` +} diff --git a/pkg/infra/models/bitbucket_project_user_permission.go b/pkg/infra/models/bitbucket_project_user_permission.go new file mode 100644 index 00000000..c08ac5c8 --- /dev/null +++ b/pkg/infra/models/bitbucket_project_user_permission.go @@ -0,0 +1,22 @@ +package models + +type BitbucketProjectUserPermissionPageScheme struct { + Size int `json:"size"` + Page int `json:"page"` + Pagelen int `json:"pagelen"` + Next string `json:"next"` + Previous string `json:"previous"` + Values []*BitbucketProjectUserPermissionScheme `json:"values"` +} + +type BitbucketProjectUserPermissionScheme struct { + Type string `json:"type"` + Links *BitbucketProjectUserPermissionLinksScheme `json:"links"` + Permission string `json:"permission"` + User *BitbucketAccountScheme `json:"user"` + Project *BitbucketProjectScheme `json:"project"` +} + +type BitbucketProjectUserPermissionLinksScheme struct { + Self *BitbucketLinkScheme `json:"self,omitempty"` +} diff --git a/pkg/infra/models/bitbucket_projects.go b/pkg/infra/models/bitbucket_projects.go index 06ad3683..a974e242 100644 --- a/pkg/infra/models/bitbucket_projects.go +++ b/pkg/infra/models/bitbucket_projects.go @@ -17,6 +17,7 @@ type BitbucketProjectScheme struct { UUID string `json:"uuid,omitempty"` // The UUID of the project. Key string `json:"key,omitempty"` // The key of the project. Name string `json:"name,omitempty"` // The name of the project. + Owner *BitbucketAccountScheme `json:"owner,omitempty"` // The owner of the project. Description string `json:"description,omitempty"` // The description of the project. IsPrivate bool `json:"is_private,omitempty"` // Whether the project is private. CreatedOn string `json:"created_on,omitempty"` // The creation time of the project. diff --git a/pkg/infra/models/bitbucket_pull_request.go b/pkg/infra/models/bitbucket_pull_request.go new file mode 100644 index 00000000..2cdab1e8 --- /dev/null +++ b/pkg/infra/models/bitbucket_pull_request.go @@ -0,0 +1,81 @@ +package models + +type BitbucketPullRequestPageScheme struct { + Size int `json:"size"` + Page int `json:"page"` + Pagelen int `json:"pagelen"` + Next string `json:"next"` + Previous string `json:"previous"` + Values []*BitbucketPullRequestScheme `json:"values"` +} + +type BitbucketPullRequestScheme struct { + Links *BitbucketPullRequestLinksScheme `json:"links,omitempty"` + Id int `json:"id,omitempty"` + Title string `json:"title,omitempty"` + Rendered *BitbucketPullRequestRenderedScheme `json:"rendered,omitempty"` + Summary *BitbucketPullRequestRenderItemScheme `json:"summary,omitempty"` + State string `json:"state,omitempty"` + Author *BitbucketAccountScheme `json:"author,omitempty"` + Source *BitbucketPullRequestEndpointScheme `json:"source,omitempty"` + Destination *BitbucketPullRequestEndpointScheme `json:"destination,omitempty"` + MergeCommit *BitbucketPullRequestCommitScheme `json:"merge_commit,omitempty"` + CommentCount int `json:"comment_count,omitempty"` + TaskCount int `json:"task_count,omitempty"` + CloseSourceBranch bool `json:"close_source_branch,omitempty"` + ClosedBy *BitbucketAccountScheme `json:"closed_by,omitempty"` + Reason string `json:"reason,omitempty"` + CreatedOn string `json:"created_on,omitempty"` + UpdatedOn string `json:"updated_on,omitempty"` + Reviewers []*BitbucketAccountScheme `json:"reviewers,omitempty"` + Participants []*BitbucketParticipantScheme `json:"participants,omitempty"` +} + +type BitbucketPullRequestLinksScheme struct { + Self *BitbucketLinkScheme `json:"self,omitempty"` + Html *BitbucketLinkScheme `json:"html,omitempty"` + Commits *BitbucketLinkScheme `json:"commits,omitempty"` + Approve *BitbucketLinkScheme `json:"approve,omitempty"` + Diff *BitbucketLinkScheme `json:"diff,omitempty"` + Diffstat *BitbucketLinkScheme `json:"diffstat,omitempty"` + Comments *BitbucketLinkScheme `json:"comments,omitempty"` + Activity *BitbucketLinkScheme `json:"activity,omitempty"` + Merge *BitbucketLinkScheme `json:"merge,omitempty"` + Decline *BitbucketLinkScheme `json:"decline,omitempty"` +} + +type BitbucketPullRequestRenderedScheme struct { + Title *BitbucketPullRequestRenderItemScheme `json:"title,omitempty"` + Description *BitbucketPullRequestRenderItemScheme `json:"description,omitempty"` + Reason *BitbucketPullRequestRenderItemScheme `json:"reason,omitempty"` +} + +type BitbucketPullRequestRenderItemScheme struct { + Raw string `json:"raw,omitempty"` + Markup string `json:"markup,omitempty"` + Html string `json:"html,omitempty"` +} + +type BitbucketPullRequestEndpointScheme struct { + Repository *RepositoryScheme `json:"repository,omitempty"` + Branch *BitbucketPullRequestBranchScheme `json:"branch,omitempty"` + Commit *BitbucketPullRequestCommitScheme `json:"commit,omitempty"` +} + +type BitbucketPullRequestBranchScheme struct { + Name string `json:"name,omitempty"` + MergeStrategies []string `json:"merge_strategies,omitempty"` + DefaultMergeStrategy string `json:"default_merge_strategy,omitempty"` +} + +type BitbucketPullRequestCommitScheme struct { + Hash string `json:"hash,omitempty"` +} + +type BitbucketParticipantScheme struct { + User *BitbucketAccountScheme `json:"user"` + Role string `json:"role"` + Approved bool `json:"approved"` + State string `json:"state"` + ParticipatedOn string `json:"participated_on"` +} diff --git a/pkg/infra/models/bitbucket_workspace.go b/pkg/infra/models/bitbucket_workspace.go index 0c88b664..6f0094d4 100644 --- a/pkg/infra/models/bitbucket_workspace.go +++ b/pkg/infra/models/bitbucket_workspace.go @@ -1,19 +1,19 @@ package models -// WorkspaceScheme represents a workspace. -type WorkspaceScheme struct { - Type string `json:"type,omitempty"` // The type of the workspace. - Links *WorkspaceLinksScheme `json:"links,omitempty"` // The links related to the workspace. - UUID string `json:"uuid,omitempty"` // The unique identifier of the workspace. - Name string `json:"name,omitempty"` // The name of the workspace. - Slug string `json:"slug,omitempty"` // The slug of the workspace. - IsPrivate bool `json:"is_private,omitempty"` // Indicates if the workspace is private. - CreatedOn string `json:"created_on,omitempty"` // The creation time of the workspace. - UpdatedOn string `json:"updated_on,omitempty"` // The update time of the workspace. +// BitbucketWorkspaceScheme represents a workspace. +type BitbucketWorkspaceScheme struct { + Type string `json:"type,omitempty"` // The type of the workspace. + Links *BitbucketWorkspaceLinksScheme `json:"links,omitempty"` // The links related to the workspace. + UUID string `json:"uuid,omitempty"` // The unique identifier of the workspace. + Name string `json:"name,omitempty"` // The name of the workspace. + Slug string `json:"slug,omitempty"` // The slug of the workspace. + IsPrivate bool `json:"is_private,omitempty"` // Indicates if the workspace is private. + CreatedOn string `json:"created_on,omitempty"` // The creation time of the workspace. + UpdatedOn string `json:"updated_on,omitempty"` // The update time of the workspace. } -// WorkspaceLinksScheme represents a collection of links related to a workspace. -type WorkspaceLinksScheme struct { +// BitbucketWorkspaceLinksScheme represents a collection of links related to a workspace. +type BitbucketWorkspaceLinksScheme struct { Avatar *BitbucketLinkScheme `json:"avatar,omitempty"` // The link to the workspace's avatar. HTML *BitbucketLinkScheme `json:"html,omitempty"` // The link to the workspace's HTML page. Members *BitbucketLinkScheme `json:"members,omitempty"` // The link to the workspace's members. diff --git a/pkg/infra/models/bitbucket_workspace_membership.go b/pkg/infra/models/bitbucket_workspace_membership.go index 34f84f6a..30bceb84 100644 --- a/pkg/infra/models/bitbucket_workspace_membership.go +++ b/pkg/infra/models/bitbucket_workspace_membership.go @@ -16,7 +16,7 @@ type WorkspaceMembershipPageScheme struct { type WorkspaceMembershipScheme struct { Links *WorkspaceMembershipLinksScheme `json:"links,omitempty"` // The links related to the membership. User *BitbucketAccountScheme `json:"user,omitempty"` // The user who has the membership. - Workspace *WorkspaceScheme `json:"workspace,omitempty"` // The workspace to which the membership applies. + Workspace *BitbucketWorkspaceScheme `json:"workspace,omitempty"` // The workspace to which the membership applies. AddedOn time.Time `json:"added_on,omitempty"` // The time when the membership was added. Permission string `json:"permission,omitempty"` // The level of the membership. LastAccessed time.Time `json:"last_accessed,omitempty"` // The last time the membership was accessed. diff --git a/pkg/infra/models/errors.go b/pkg/infra/models/errors.go index 730301c3..218a4add 100644 --- a/pkg/infra/models/errors.go +++ b/pkg/infra/models/errors.go @@ -172,4 +172,8 @@ var ( ErrNoMemberID = errors.New("bitbucket: no member id set") ErrNoWebhookID = errors.New("bitbucket: no webhook id set") ErrNoRepository = errors.New("bitbucket: no repository set") + ErrNoProjectSlug = errors.New("bitbucket: no project slug set") + ErrNoAccountSlug = errors.New("bitbucket: no account slug set") + ErrNoGroupSlug = errors.New("bitbucket: no group slug set") + ErrNoPermissionSlug = errors.New("bitbucket: no permission set") ) diff --git a/service/bitbucket/project.go b/service/bitbucket/project.go new file mode 100644 index 00000000..f0042c4f --- /dev/null +++ b/service/bitbucket/project.go @@ -0,0 +1,83 @@ +package bitbucket + +import ( + "context" + "github.com/ctreminiom/go-atlassian/pkg/infra/models" +) + +// ProjectConnector defines the interface for project-related operations in Bitbucket. +type ProjectConnector interface { + + // Create creates a new project in the specified workspace. + // + // POST /2.0/workspaces/{workspace}/projects + // + // Parameters: + // - ctx: The context for the request. + // - workspace: The workspace identifier where the project will be created. + // - payload: The project details to be created. + // + // Returns: + // - A pointer to the created BitbucketProjectScheme. + // - A pointer to the response scheme. + // - An error if the creation fails. + // + // https://docs.go-atlassian.io/bitbucket-cloud/workspace + Create(ctx context.Context, workspace string, payload *models.BitbucketProjectScheme) (*models.BitbucketProjectScheme, *models.ResponseScheme, error) + + // Get retrieves a project from the specified workspace using the project key. + // + // GET /2.0/workspaces/{workspace}/projects/{project_key} + // + // Parameters: + // - ctx: The context for the request. + // - workspace: The workspace identifier where the project is located. + // - projectKey: The key of the project to be retrieved. + // + // Returns: + // - A pointer to the retrieved BitbucketProjectScheme. + // - A pointer to the response scheme. + // - An error if the retrieval fails. + // + // https://docs.go-atlassian.io/bitbucket-cloud/workspace + Get(ctx context.Context, workspace, projectKey string) (*models.BitbucketProjectScheme, *models.ResponseScheme, error) + + // Update updates an existing project in the specified workspace using the project key. + // + // Since this endpoint can be used to both update and to create a project, the request body depends on the intent. + // + // + // Parameters: + // - ctx: The context for the request. + // - workspace: The workspace identifier where the project is located. + // - projectKey: The key of the project to be updated. + // - payload: The project details to be updated. + // + // Returns: + // - A pointer to the updated BitbucketProjectScheme. + // - A pointer to the response scheme. + // - An error if the update fails. + // + // https://docs.go-atlassian.io/bitbucket-cloud/workspace + Update(ctx context.Context, workspace, projectKey string, payload *models.BitbucketProjectScheme) (*models.BitbucketProjectScheme, *models.ResponseScheme, error) + + // Delete removes a project from the specified workspace using the project key. + // + // This is an irreversible operation. + // You cannot delete a project that still contains repositories. + // To delete the project, delete or transfer the repositories first. + // + // DELETE /2.0/workspaces/{workspace}/projects/{project_key} + // + // Parameters: + // - ctx: The context for the request. + // - workspace: The workspace identifier where the project is located. + // - projectKey: The key of the project to be deleted. + // + // Returns: + // - A pointer to the response scheme. + // - An error if the deletion fails. + // + // https://docs.go-atlassian.io/bitbucket-cloud/workspace + Delete(ctx context.Context, workspace, projectKey string) (*models.ResponseScheme, error) +} diff --git a/service/bitbucket/project_permission_group.go b/service/bitbucket/project_permission_group.go new file mode 100644 index 00000000..65f571f5 --- /dev/null +++ b/service/bitbucket/project_permission_group.go @@ -0,0 +1,82 @@ +package bitbucket + +import ( + "context" + "github.com/ctreminiom/go-atlassian/pkg/infra/models" +) + +type ProjectGroupPermissionConnector interface { + + // Gets returns a paginated list of explicit group permissions for the given project. + // + // GET /2.0/workspaces/{workspace}/projects/{project_key}/permissions-config/groups + // + // Parameters: + // - ctx: The context for the request. + // - workspace: The workspace identifier where the project is located. + // - projectKey: The key of the project + // + // Returns: + // - A pointer to the updated BitbucketProjectGroupPermissionPageScheme. + // - A pointer to the response scheme. + // - An error if the update fails. + // + // https://docs.go-atlassian.io/bitbucket-cloud/workspace + Gets(ctx context.Context, workspace, projectKey string) (*models.BitbucketProjectGroupPermissionPageScheme, *models.ResponseScheme, error) + + // Get retrieves the explicit group permissions for a specific group in the given project. + // + // GET /2.0/workspaces/{workspace}/projects/{project_key}/permissions-config/groups/{group_slug} + // + // Parameters: + // - ctx: The context for the request. + // - workspace: The workspace identifier where the project is located. + // - projectKey: The key of the project + // - groupSlug: The slug of the group whose permissions are to be retrieved. + // + // Returns: + // - A pointer to the ProjectGroupPermissionScheme. + // - A pointer to the response scheme. + // - An error if the retrieval fails. + // + // https://docs.go-atlassian.io/bitbucket-cloud/workspace + Get(ctx context.Context, workspace, projectKey, groupSlug string) (*models.ProjectGroupPermissionScheme, *models.ResponseScheme, error) + + // Update updates the explicit group permissions for a specific group in the given project. + // + // PUT /2.0/workspaces/{workspace}/projects/{project_key}/permissions-config/groups/{group_slug} + // + // Parameters: + // - ctx: The context for the request. + // - workspace: The workspace identifier where the project is located. + // - projectKey: The key of the project. + // - groupSlug: The slug of the group whose permissions are to be updated. + // - permission: The new permission level to be set for the group. + // + // Returns: + // - A pointer to the ProjectGroupPermissionScheme. + // - A pointer to the response scheme. + // - An error if the update fails. + // + // https://docs.go-atlassian.io/bitbucket-cloud/workspace + Update(ctx context.Context, workspace, projectKey, groupSlug, permission string) (*models.ProjectGroupPermissionScheme, *models.ResponseScheme, error) + + // Delete removes the explicit group permissions for a specific group in the given project. + // + // Only users with admin permission for the project may access this resource. + // + // DELETE /2.0/workspaces/{workspace}/projects/{project_key}/permissions-config/groups/{group_slug} + // + // Parameters: + // - ctx: The context for the request. + // - workspace: The workspace identifier where the project is located. + // - projectKey: The key of the project. + // - groupSlug: The slug of the group whose permissions are to be deleted. + // + // Returns: + // - A pointer to the response scheme. + // - An error if the deletion fails. + // + // https://docs.go-atlassian.io/bitbucket-cloud/workspace + Delete(ctx context.Context, workspace, projectKey, groupSlug string) (*models.ResponseScheme, error) +} diff --git a/service/bitbucket/project_permission_user.go b/service/bitbucket/project_permission_user.go new file mode 100644 index 00000000..faeeb398 --- /dev/null +++ b/service/bitbucket/project_permission_user.go @@ -0,0 +1,90 @@ +package bitbucket + +import ( + "context" + "github.com/ctreminiom/go-atlassian/pkg/infra/models" +) + +type ProjectUserPermissionConnector interface { + + // Gets returns a paginated list of explicit user permissions for the given project. + // + // GET /2.0/workspaces/{workspace}/projects/{project_key}/permissions-config/users + // + // Parameters: + // - ctx: The context for the request. + // - workspace: The workspace identifier where the project is located. + // - projectKey: The key of the project + // + // Returns: + // - A pointer to the updated BitbucketProjectUserPermissionPageScheme. + // - A pointer to the response scheme. + // - An error if the update fails. + // + // https://docs.go-atlassian.io/bitbucket-cloud/workspace + Gets(ctx context.Context, workspace, projectKey string) (*models.BitbucketProjectUserPermissionPageScheme, *models.ResponseScheme, error) + + // Get retrieves the explicit user permissions for a specific user in the given project. + // + // Only users with admin permission for the project may access this resource. + // + // Permissions can be: "admin", "write", "read", "create-repo" or "none". + // + // GET /2.0/workspaces/{workspace}/projects/{project_key}/permissions-config/users/{selected_user_id} + // + // Parameters: + // - ctx: The context for the request. + // - workspace: The workspace identifier where the project is located. + // - projectKey: The key of the project. + // - userSlug: The slug of the user whose permissions are to be retrieved. + // + // Returns: + // - A pointer to the BitbucketProjectUserPermissionScheme. + // - A pointer to the response scheme. + // - An error if the retrieval fails. + // + // https://docs.go-atlassian.io/bitbucket-cloud/workspace + Get(ctx context.Context, workspace, projectKey, userSlug string) (*models.BitbucketProjectUserPermissionScheme, *models.ResponseScheme, error) + + // Update updates the explicit user permission for a given user and project. + // + // The selected user must be a member of the workspace, and cannot be the workspace + // + // Only users with admin permission for the project may access this resource. + // + // Due to security concerns, the JWT and OAuth authentication methods are unsupported. This is to ensure integrations and add-ons are not allowed to change permissions. + // + // PUT /2.0/workspaces/{workspace}/projects/{project_key}/permissions-config/users/{selected_user_id} + // + // Parameters: + // - ctx: The context for the request. + // - workspace: The workspace identifier where the project is located. + // - projectKey: The key of the project. + // - userSlug: The slug of the user whose permissions are to be updated. + // - permission: The new permission level to be set for the user. + // + // Returns: + // - A pointer to the BitbucketProjectUserPermissionScheme. + // - A pointer to the response scheme. + // - An error if the update fails. + // + // https://docs.go-atlassian.io/bitbucket-cloud/workspace + Update(ctx context.Context, workspace, projectKey, userSlug, permission string) (*models.BitbucketProjectUserPermissionScheme, *models.ResponseScheme, error) + + // Delete removes the explicit user permissions for a specific user in the given project. + // + // DELETE /2.0/workspaces/{workspace}/projects/{project_key}/permissions-config/users/{selected_user_id} + // + // Parameters: + // - ctx: The context for the request. + // - workspace: The workspace identifier where the project is located. + // - projectKey: The key of the project. + // - userSlug: The slug of the user whose permissions are to be deleted. + // + // Returns: + // - A pointer to the response scheme. + // - An error if the deletion fails. + // + // https://docs.go-atlassian.io/bitbucket-cloud/workspace + Delete(ctx context.Context, workspace, projectKey, userSlug string) (*models.ResponseScheme, error) +} diff --git a/service/bitbucket/project_reviewer.go b/service/bitbucket/project_reviewer.go new file mode 100644 index 00000000..2e74f5dc --- /dev/null +++ b/service/bitbucket/project_reviewer.go @@ -0,0 +1,81 @@ +package bitbucket + +import ( + "context" + "github.com/ctreminiom/go-atlassian/pkg/infra/models" +) + +type ProjectReviewerConnector interface { + + // Gets returns a list of all default reviewers for a project. + // + // This is a list of users that will be added as default reviewers to pull requests for any repository within the project. + // + // GET /2.0/workspaces/{workspace}/projects/{project_key}/default-reviewers + // + // Parameters: + // - ctx: The context for the request. + // - workspace: The workspace identifier where the project is located. + // - projectKey: The key of the project to be updated. + // + // Returns: + // - A pointer to the updated ProjectReviewerPageScheme. + // - A pointer to the response scheme. + // - An error if the update fails. + // + // https://docs.go-atlassian.io/bitbucket-cloud/workspace + Gets(ctx context.Context, workspace, projectKey string) (*models.ProjectReviewerPageScheme, *models.ResponseScheme, error) + + // Get retrieves a specific project reviewer based on the provided parameters. + // + // GET /2.0/workspaces/{workspace}/projects/{project_key}/default-reviewers/{selected_user} + // + // Parameters: + // - ctx: The context for the request. + // - workspace: The workspace identifier where the project is located. + // - projectKey: The key of the project to be updated. + // - userSlug: The slug of the user to be retrieved. + // + // Returns: + // - A pointer to the ProjectReviewerScheme. + // - A pointer to the response scheme. + // - An error if the retrieval fails. + // + // https://docs.go-atlassian.io/bitbucket-cloud/workspace + Get(ctx context.Context, workspace, projectKey, userSlug string) (*models.ProjectReviewerScheme, *models.ResponseScheme, error) + + // Add adds a specific user as a default reviewer for a project. + // + // PUT /2.0/workspaces/{workspace}/projects/{project_key}/default-reviewers/{selected_user} + // + // Parameters: + // - ctx: The context for the request. + // - workspace: The workspace identifier where the project is located. + // - projectKey: The key of the project to be updated. + // - userSlug: The slug of the user to be added as a default reviewer. + // + // Returns: + // - A pointer to the ProjectReviewerScheme. + // - A pointer to the response scheme. + // - An error if the addition fails. + // + // https://docs.go-atlassian.io/bitbucket-cloud/workspace + Add(ctx context.Context, workspace, projectKey, userSlug string) (*models.ProjectReviewerScheme, *models.ResponseScheme, error) + + // Remove deletes a specific user from the default reviewers for a project. + // + // DELETE /2.0/workspaces/{workspace}/projects/{project_key}/default-reviewers/{selected_user} + // + // Parameters: + // - ctx: The context for the request. + // - workspace: The workspace identifier where the project is located. + // - projectKey: The key of the project to be updated. + // - userSlug: The slug of the user to be removed as a default reviewer. + // + // Returns: + // - A pointer to the response scheme. + // - An error if the removal fails. + // + // https://docs.go-atlassian.io/bitbucket-cloud/workspace + Remove(ctx context.Context, workspace, projectKey, userSlug string) (*models.ResponseScheme, error) +} diff --git a/service/bitbucket/pull_request.go b/service/bitbucket/pull_request.go new file mode 100644 index 00000000..dc1e4aed --- /dev/null +++ b/service/bitbucket/pull_request.go @@ -0,0 +1,15 @@ +package bitbucket + +import ( + "context" + "github.com/ctreminiom/go-atlassian/pkg/infra/models" +) + +type PullRequestConnector interface { + Gets(ctx context.Context, workspace, repoSlug, state string) (*models.BitbucketPullRequestPageScheme, *models.ResponseScheme, error) + Get(ctx context.Context, workspace, repoSlug, pullRequestID string) (*models.BitbucketPullRequestScheme, *models.ResponseScheme, error) + Create(ctx context.Context, workspace, repoSlug string, payload *models.BitbucketPullRequestScheme) (*models.BitbucketPullRequestScheme, *models.ResponseScheme, error) + Update(ctx context.Context, workspace, repoSlug, pullRequestID string, payload *models.BitbucketPullRequestScheme) (*models.BitbucketPullRequestScheme, *models.ResponseScheme, error) + Approve(ctx context.Context, workspace, repoSlug, pullRequestID string) (*models.BitbucketParticipantScheme, *models.ResponseScheme, error) + Unapprove(ctx context.Context, workspace, repoSlug, pullRequestID string) (*models.ResponseScheme, error) +} diff --git a/service/bitbucket/workspace.go b/service/bitbucket/workspace.go index 6ffa1304..59106137 100644 --- a/service/bitbucket/workspace.go +++ b/service/bitbucket/workspace.go @@ -18,7 +18,7 @@ type WorkspaceConnector interface { // GET /2.0/workspaces/{workspace} // // https://docs.go-atlassian.io/bitbucket-cloud/workspace#get-a-workspace - Get(ctx context.Context, workspace string) (*models.WorkspaceScheme, *models.ResponseScheme, error) + Get(ctx context.Context, workspace string) (*models.BitbucketWorkspaceScheme, *models.ResponseScheme, error) // Members returns all members of the requested workspace. //