Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Convert team and scoped user role service #217

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions pkg/scopeduserroles/scoped_user_role.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package scopeduserroles

import (
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/resources"
"github.com/go-playground/validator/v10"
)

type ScopedUserRole struct {
EnvironmentIDs []string `json:"EnvironmentIds,omitempty"`
ProjectIDs []string `json:"ProjectIds,omitempty"`
ProjectGroupIDs []string `json:"ProjectGroupIds,omitempty"`
TeamID string `json:"TeamId" validate:"required"`
TenantIDs []string `json:"TenantIds,omitempty"`
SpaceID string `json:"SpaceId"`
UserRoleID string `json:"UserRoleId" validate:"required"`

resources.Resource
}

func NewScopedUserRole(userRoleId string, teamId string) *ScopedUserRole {
return &ScopedUserRole{
UserRoleID: userRoleId,
TeamID: teamId,
Resource: *resources.NewResource(),
}
}

// Validate checks the state of the scoped user role and returns an error if invalid.
func (r *ScopedUserRole) Validate() error {
return validator.New().Struct(r)
}
10 changes: 10 additions & 0 deletions pkg/scopeduserroles/scoped_user_role_query.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package scopeduserroles

type ScopedUserRolesQuery struct {
IDs []string `uri:"ids,omitempty" url:"ids,omitempty"`
IncludeSystem bool `uri:"includeSystem,omitempty" url:"includeSystem,omitempty"`
PartialName string `uri:"partialName,omitempty" url:"partialName,omitempty"`
Skip int `uri:"skip,omitempty" url:"skip,omitempty"`
Spaces []string `uri:"spaces,omitempty" url:"spaces,omitempty"`
Take int `uri:"take,omitempty" url:"take,omitempty"`
}
35 changes: 35 additions & 0 deletions pkg/scopeduserroles/scoped_user_role_service.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package scopeduserroles

import (
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/newclient"
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/resources"
)

// --- new ---
const template = "/api/scopeduserroles{/id}{?skip,take,ids,partialName,spaces,includeSystem}"

// Add creates a new scoped user role.
func Add(client newclient.Client, scopedUserRole *ScopedUserRole) (*ScopedUserRole, error) {
return newclient.Add[ScopedUserRole](client, template, scopedUserRole.SpaceID, scopedUserRole)
}

// Get returns a collection of scoped user roles based on the criteria defined by
// its input query parameter.
func Get(client newclient.Client, spaceID string, scopedUserRolesQuery ScopedUserRolesQuery) (*resources.Resources[*ScopedUserRole], error) {
return newclient.GetByQuery[ScopedUserRole](client, template, spaceID, scopedUserRolesQuery)
}

// GetByID returns the scoped user role that matches the input ID.
func GetByID(client newclient.Client, spaceID string, ID string) (*ScopedUserRole, error) {
return newclient.GetByID[ScopedUserRole](client, template, spaceID, ID)
}

// Update modifies a ScopedUserRole based on the one provided as input.
func Update(client newclient.Client, scopedUserRole *ScopedUserRole) (*ScopedUserRole, error) {
return newclient.Update[ScopedUserRole](client, template, scopedUserRole.SpaceID, scopedUserRole.ID, scopedUserRole)
}

// DeleteByID deletes a scoped user role that matches the input ID
func DeleteByID(client newclient.Client, spaceID string, ID string) error {
return newclient.DeleteByID(client, template, spaceID, ID)
}
84 changes: 84 additions & 0 deletions pkg/teams/team_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import (
"github.com/OctopusDeploy/go-octopusdeploy/v2/internal"
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/constants"
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/core"
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/newclient"
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/resources"
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/scopeduserroles"
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/services"
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/services/api"
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/userroles"
Expand All @@ -25,6 +27,8 @@ func NewTeamService(sling *sling.Sling, uriTemplate string) *TeamService {
}

// Add creates a new team.
//
// Deprecated: use teams.Add()
func (s *TeamService) Add(team *Team) (*Team, error) {
if IsNil(team) {
return nil, internal.CreateInvalidParameterError(constants.OperationAdd, constants.ParameterTeam)
Expand All @@ -46,6 +50,8 @@ func (s *TeamService) Add(team *Team) (*Team, error) {
// Delete will delete a team if it is not a built-in team (i.e. the field,
// CanBeDeleted is true). If the team cannot be deleted or an error occurs, it
// returns an error.
//
// Deprecated: use teams.Delete()
func (s *TeamService) Delete(team *Team) error {
if team == nil {
return internal.CreateInvalidParameterError(constants.OperationDelete, constants.ParameterTeam)
Expand All @@ -62,6 +68,8 @@ func (s *TeamService) Delete(team *Team) error {
// Get returns a collection of teams based on the criteria defined by its input
// query parameter. If an error occurs, an empty collection is returned along
// with the associated error.
//
// Deprecated: use teams.Get()
func (s *TeamService) Get(teamsQuery TeamsQuery) (*resources.Resources[*Team], error) {
path, err := s.GetURITemplate().Expand(teamsQuery)
if err != nil {
Expand All @@ -78,6 +86,8 @@ func (s *TeamService) Get(teamsQuery TeamsQuery) (*resources.Resources[*Team], e

// GetAll returns all teams. If none can be found or an error occurs, it
// returns an empty collection.
//
// Deprecated: use teams.GetAll()
func (s *TeamService) GetAll() ([]*Team, error) {
items := []*Team{}
path, err := services.GetAllPath(s)
Expand All @@ -91,6 +101,8 @@ func (s *TeamService) GetAll() ([]*Team, error) {

// GetByID returns the team that matches the input ID. If one cannot be found,
// it returns nil and an error.
//
// Deprecated: use teams.GetById()
func (s *TeamService) GetByID(id string) (*Team, error) {
if internal.IsEmpty(id) {
return nil, internal.CreateInvalidParameterError(constants.OperationGetByID, constants.ParameterID)
Expand Down Expand Up @@ -125,6 +137,8 @@ func (s *TeamService) GetByPartialName(partialName string) ([]*Team, error) {
}

// Update modifies a team based on the one provided as input.
//
// Deprecated: use teams.Update()
func (s *TeamService) Update(team *Team) (*Team, error) {
path, err := services.GetUpdatePath(s, team)
if err != nil {
Expand All @@ -139,6 +153,9 @@ func (s *TeamService) Update(team *Team) (*Team, error) {
return resp.(*Team), nil
}

// GetScopedUserRoles returns user scoped roles scoped to the team provided
//
// Deprecated: use teams.GetScopedUserRoles()
func (s *TeamService) GetScopedUserRoles(team Team, query core.SkipTakeQuery) (*resources.Resources[*userroles.ScopedUserRole], error) {
template, _ := uritemplates.Parse(team.Links["ScopedUserRoles"])
path, _ := template.Expand(query)
Expand All @@ -150,3 +167,70 @@ func (s *TeamService) GetScopedUserRoles(team Team, query core.SkipTakeQuery) (*

return resp.(*resources.Resources[*userroles.ScopedUserRole]), nil
}

// --- new ---

const template = "/api/{spaceId}/teams{/id}{?skip,take,ids,partialName}"
const scopedUserRolesTemplate = "/api/teams{/id}/scopeduserroles{?skip,take}"

// Add creates a new team.
func Add(client newclient.Client, team *Team) (*Team, error) {
return newclient.Add[Team](client, template, team.SpaceID, team)
}

// Get returns a collection of teams based on the criteria defined by its
// input query parameter.
func Get(client newclient.Client, spaceID string, teamsQuery TeamsQuery) (*resources.Resources[*Team], error) {
return newclient.GetByQuery[Team](client, template, spaceID, teamsQuery)
}

// GetByID returns the team that matches the input ID.
func GetByID(client newclient.Client, spaceID string, ID string) (*Team, error) {
return newclient.GetByID[Team](client, template, spaceID, ID)
}

// Update modifies a team based on the one provided as input.
func Update(client newclient.Client, team *Team) (*Team, error) {
return newclient.Update[Team](client, template, team.SpaceID, team.ID, team)
}

// GetAll returns all teams. If an error occurs, it returns nil.
func GetAll(client newclient.Client, spaceID string) ([]*Team, error) {
return newclient.GetAll[Team](client, template, spaceID)
}

// Delete will delete a team if it is not a built-in team (i.e. the field,
// CanBeDeleted is true). If the team cannot be deleted or an error occurs, it
// returns an error.
func Delete(client newclient.Client, team *Team) error {
if team == nil {
return internal.CreateInvalidParameterError(constants.OperationDelete, constants.ParameterTeam)
}

if !team.CanBeDeleted {
return internal.CreateBuiltInTeamsCannotDeleteError()
}

return newclient.DeleteByID(client, template, team.SpaceID, team.ID)
}

// GetScopedUserRoles returns scoped user roles scoped to the team provided
func GetScopedUserRoles(client newclient.Client, team *Team, query core.SkipTakeQuery) (*resources.Resources[*scopeduserroles.ScopedUserRole], error) {
values, _ := uritemplates.Struct2map(query)
if values == nil {
values = map[string]any{}
}

values["id"] = team.ID
path, err := client.URITemplateCache().Expand(scopedUserRolesTemplate, values)
if err != nil {
return nil, err
}

res, err := newclient.Get[resources.Resources[*scopeduserroles.ScopedUserRole]](client.HttpSession(), path)
if err != nil {
return nil, err
}

return res, nil
}
5 changes: 5 additions & 0 deletions pkg/userroles/scoped_user_role_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ func NewScopedUserRoleService(sling *sling.Sling, uriTemplate string) *ScopedUse
}
}

// Deprecated: use scopeduserroles.Add()
func (s *ScopedUserRoleService) Add(scopedUserRole *ScopedUserRole) (*ScopedUserRole, error) {
if IsNil(scopedUserRole) {
return nil, internal.CreateInvalidParameterError(constants.OperationAdd, constants.ParameterScopedUserRole)
Expand All @@ -44,6 +45,8 @@ func (s *ScopedUserRoleService) Add(scopedUserRole *ScopedUserRole) (*ScopedUser

// Currently no known query params, not even take and skip
// Query params could exist, but are undocumented in the swagger
//
// Deprecated: use scopeduserroles.Get()
func (s *ScopedUserRoleService) Get() (*resources.Resources[*ScopedUserRole], error) {
path := s.BasePath

Expand All @@ -54,6 +57,7 @@ func (s *ScopedUserRoleService) Get() (*resources.Resources[*ScopedUserRole], er
return resp.(*resources.Resources[*ScopedUserRole]), nil
}

// Deprecated: use scopeduserroles.GetById()
func (s *ScopedUserRoleService) GetByID(id string) (*ScopedUserRole, error) {
if internal.IsEmpty(id) {
return nil, internal.CreateInvalidParameterError(constants.OperationGetByID, constants.ParameterID)
Expand All @@ -71,6 +75,7 @@ func (s *ScopedUserRoleService) GetByID(id string) (*ScopedUserRole, error) {
return resp.(*ScopedUserRole), nil
}

// Deprecated: use scopeduserroles.Update()
func (s *ScopedUserRoleService) Update(scopedUserRole *ScopedUserRole) (*ScopedUserRole, error) {
if scopedUserRole == nil {
return nil, internal.CreateInvalidParameterError(constants.OperationUpdate, constants.ParameterScopedUserRole)
Expand Down
83 changes: 83 additions & 0 deletions test/e2e/scoped_user_role_service_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package e2e

import (
"testing"

"github.com/OctopusDeploy/go-octopusdeploy/v2/internal"
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/client"
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/scopeduserroles"
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/userroles"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestScopedUserRoleService_AddGetUpdateDelete(t *testing.T) {
client := getOctopusClient()
require.NotNil(t, client)

// Create user role with at least 1 space permission
name := internal.GetRandomName()
userrole := userroles.NewUserRole(name)
userrole.GrantedSpacePermissions = []string{"ProjectView"}
require.NoError(t, userrole.Validate())

createdUserRole, err := userroles.Add(client, userrole)
require.NotNil(t, createdUserRole)
require.NoError(t, err)

team := CreateTestTeam_NewClient(t, client)
require.NotNil(t, team)

// Add
scopedUserRole := scopeduserroles.NewScopedUserRole(createdUserRole.ID, team.ID)
scopedUserRole.SpaceID = client.GetSpaceID()
require.NoError(t, scopedUserRole.Validate())

createdRole, err := scopeduserroles.Add(client, scopedUserRole)
require.NotNil(t, createdRole)
require.NoError(t, err)

// Get
userRoleToCompare, err := scopeduserroles.GetByID(client, createdRole.SpaceID, createdRole.GetID())
require.NotNil(t, userRoleToCompare)
require.NoError(t, err)

AssertEqualScopedUserRoles(t, createdRole, userRoleToCompare)

// Update
updatedRole, err := scopeduserroles.Update(client, createdRole)
require.Nil(t, err)
assert.EqualValues(t, createdRole.ID, updatedRole.ID)
assert.EqualValues(t, createdRole.TeamID, updatedRole.TeamID)

t.Cleanup(func() {
DeleteScopedUserRole(t, client, createdRole)
DeleteTestUserRole_NewClient(t, client, createdUserRole)
DeleteTestTeam_NewClient(t, client, team)
})
}

func DeleteScopedUserRole(t *testing.T, client *client.Client, scopedUserRole *scopeduserroles.ScopedUserRole) {
require.NotNil(t, scopedUserRole)

if client == nil {
client = getOctopusClient()
}
require.NotNil(t, client)

err := scopeduserroles.DeleteByID(client, scopedUserRole.SpaceID, scopedUserRole.GetID())
assert.NoError(t, err)

// verify the delete operation was successful
deletedUserRole, err := scopeduserroles.GetByID(client, scopedUserRole.SpaceID, scopedUserRole.GetID())
assert.Error(t, err)
assert.Nil(t, deletedUserRole)
}

func AssertEqualScopedUserRoles(t *testing.T, expected *scopeduserroles.ScopedUserRole, actual *scopeduserroles.ScopedUserRole) {
assert.Equal(t, expected.GetID(), actual.GetID())
assert.Equal(t, expected.UserRoleID, actual.UserRoleID)
assert.Equal(t, expected.SpaceID, actual.SpaceID)
assert.Equal(t, expected.TeamID, actual.TeamID)
assert.True(t, internal.IsLinksEqual(expected.Links, actual.Links))
}
Loading