diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ac71f0ad..e40f6c3f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,5 @@ # Unreleased +* Adds `ManageTeams`, `ManageOrganizationAccess`, and `AccessSecretTeams` permissions to team `OrganizationAccess` by @juliannatetreault [#874](https://github.com/hashicorp/go-tfe/pull/874) # v1.52.0 diff --git a/team.go b/team.go index 298551f07..dcee1d7b7 100644 --- a/team.go +++ b/team.go @@ -61,17 +61,20 @@ type Team struct { // OrganizationAccess represents the team's permissions on its organization type OrganizationAccess struct { - ManagePolicies bool `jsonapi:"attr,manage-policies"` - ManagePolicyOverrides bool `jsonapi:"attr,manage-policy-overrides"` - ManageWorkspaces bool `jsonapi:"attr,manage-workspaces"` - ManageVCSSettings bool `jsonapi:"attr,manage-vcs-settings"` - ManageProviders bool `jsonapi:"attr,manage-providers"` - ManageModules bool `jsonapi:"attr,manage-modules"` - ManageRunTasks bool `jsonapi:"attr,manage-run-tasks"` - ManageProjects bool `jsonapi:"attr,manage-projects"` - ReadWorkspaces bool `jsonapi:"attr,read-workspaces"` - ReadProjects bool `jsonapi:"attr,read-projects"` - ManageMembership bool `jsonapi:"attr,manage-membership"` + ManagePolicies bool `jsonapi:"attr,manage-policies"` + ManagePolicyOverrides bool `jsonapi:"attr,manage-policy-overrides"` + ManageWorkspaces bool `jsonapi:"attr,manage-workspaces"` + ManageVCSSettings bool `jsonapi:"attr,manage-vcs-settings"` + ManageProviders bool `jsonapi:"attr,manage-providers"` + ManageModules bool `jsonapi:"attr,manage-modules"` + ManageRunTasks bool `jsonapi:"attr,manage-run-tasks"` + ManageProjects bool `jsonapi:"attr,manage-projects"` + ReadWorkspaces bool `jsonapi:"attr,read-workspaces"` + ReadProjects bool `jsonapi:"attr,read-projects"` + ManageMembership bool `jsonapi:"attr,manage-membership"` + ManageTeams bool `jsonapi:"attr,manage-teams"` + ManageOrganizationAccess bool `jsonapi:"attr,manage-organization-access"` + AccessSecretTeams bool `jsonapi:"attr,access-secret-teams"` } // TeamPermissions represents the current user's permissions on the team. @@ -147,17 +150,20 @@ type TeamUpdateOptions struct { // OrganizationAccessOptions represents the organization access options of a team. type OrganizationAccessOptions struct { - ManagePolicies *bool `json:"manage-policies,omitempty"` - ManagePolicyOverrides *bool `json:"manage-policy-overrides,omitempty"` - ManageWorkspaces *bool `json:"manage-workspaces,omitempty"` - ManageVCSSettings *bool `json:"manage-vcs-settings,omitempty"` - ManageProviders *bool `json:"manage-providers,omitempty"` - ManageModules *bool `json:"manage-modules,omitempty"` - ManageRunTasks *bool `json:"manage-run-tasks,omitempty"` - ManageProjects *bool `json:"manage-projects,omitempty"` - ReadWorkspaces *bool `json:"read-workspaces,omitempty"` - ReadProjects *bool `json:"read-projects,omitempty"` - ManageMembership *bool `json:"manage-membership,omitempty"` + ManagePolicies *bool `json:"manage-policies,omitempty"` + ManagePolicyOverrides *bool `json:"manage-policy-overrides,omitempty"` + ManageWorkspaces *bool `json:"manage-workspaces,omitempty"` + ManageVCSSettings *bool `json:"manage-vcs-settings,omitempty"` + ManageProviders *bool `json:"manage-providers,omitempty"` + ManageModules *bool `json:"manage-modules,omitempty"` + ManageRunTasks *bool `json:"manage-run-tasks,omitempty"` + ManageProjects *bool `json:"manage-projects,omitempty"` + ReadWorkspaces *bool `json:"read-workspaces,omitempty"` + ReadProjects *bool `json:"read-projects,omitempty"` + ManageMembership *bool `json:"manage-membership,omitempty"` + ManageTeams *bool `json:"manage-teams,omitempty"` + ManageOrganizationAccess *bool `json:"manage-organization-access,omitempty"` + AccessSecretTeams *bool `json:"access-secret-teams,omitempty"` } // List all the teams of the given organization. diff --git a/team_integration_test.go b/team_integration_test.go index 77d17aff5..04a1306be 100644 --- a/team_integration_test.go +++ b/team_integration_test.go @@ -482,3 +482,132 @@ func TestTeamsUpdateManageManageMembership(t *testing.T) { originalTeamAccess.ManageMembership = true assert.Equal(t, originalTeamAccess, refreshed.OrganizationAccess) } + +func TestTeamsUpdateManageTeams(t *testing.T) { + client := testClient(t) + ctx := context.Background() + + orgTest, orgTestCleanup := createOrganization(t, client) + defer orgTestCleanup() + + tmTest, tmTestCleanup := createTeam(t, client, orgTest) + defer tmTestCleanup() + + teamRead, err := client.Teams.Read(ctx, tmTest.ID) + require.NoError(t, err) + assert.False(t, teamRead.OrganizationAccess.ManageTeams, "manage teams is false by default") + + originalTeamAccess := teamRead.OrganizationAccess + + options := TeamUpdateOptions{ + OrganizationAccess: &OrganizationAccessOptions{ + // **Note: ManageTeams requires ManageMembership.** + ManageMembership: Bool(true), + ManageTeams: Bool(true), + }, + } + + tm, err := client.Teams.Update(ctx, tmTest.ID, options) + require.NoError(t, err) + assert.True(t, tm.OrganizationAccess.ManageMembership) + assert.True(t, tm.OrganizationAccess.ManageTeams) + + refreshed, err := client.Teams.Read(ctx, tmTest.ID) + require.NoError(t, err) + assert.True(t, refreshed.OrganizationAccess.ManageMembership) + assert.True(t, refreshed.OrganizationAccess.ManageTeams) + + // Check that other org access fields are not updated + originalTeamAccess.ManageMembership = true + originalTeamAccess.ManageTeams = true + assert.Equal(t, originalTeamAccess, refreshed.OrganizationAccess) +} + +func TestTeamsUpdateManageOrganizationAccess(t *testing.T) { + client := testClient(t) + ctx := context.Background() + + orgTest, orgTestCleanup := createOrganization(t, client) + defer orgTestCleanup() + + tmTest, tmTestCleanup := createTeam(t, client, orgTest) + defer tmTestCleanup() + + teamRead, err := client.Teams.Read(ctx, tmTest.ID) + require.NoError(t, err) + assert.False(t, teamRead.OrganizationAccess.ManageOrganizationAccess, "manage organization access is false by default") + + originalTeamAccess := teamRead.OrganizationAccess + + options := TeamUpdateOptions{ + OrganizationAccess: &OrganizationAccessOptions{ + // **Note: ManageOrganizationAccess requires ManageMembership and ManageTeams.** + ManageMembership: Bool(true), + ManageTeams: Bool(true), + ManageOrganizationAccess: Bool(true), + }, + } + + tm, err := client.Teams.Update(ctx, tmTest.ID, options) + require.NoError(t, err) + assert.True(t, tm.OrganizationAccess.ManageMembership) + assert.True(t, tm.OrganizationAccess.ManageTeams) + assert.True(t, tm.OrganizationAccess.ManageOrganizationAccess) + + refreshed, err := client.Teams.Read(ctx, tmTest.ID) + require.NoError(t, err) + assert.True(t, refreshed.OrganizationAccess.ManageMembership) + assert.True(t, refreshed.OrganizationAccess.ManageTeams) + assert.True(t, refreshed.OrganizationAccess.ManageOrganizationAccess) + + // Check that other org access fields are not updated + originalTeamAccess.ManageMembership = true + originalTeamAccess.ManageTeams = true + originalTeamAccess.ManageOrganizationAccess = true + assert.Equal(t, originalTeamAccess, refreshed.OrganizationAccess) +} + +func TestTeamsUpdateAccessSecretTeams(t *testing.T) { + client := testClient(t) + ctx := context.Background() + + orgTest, orgTestCleanup := createOrganization(t, client) + defer orgTestCleanup() + + tmTest, tmTestCleanup := createTeam(t, client, orgTest) + defer tmTestCleanup() + + teamRead, err := client.Teams.Read(ctx, tmTest.ID) + require.NoError(t, err) + assert.False(t, teamRead.OrganizationAccess.AccessSecretTeams, "access secret teams is false by default") + + originalTeamAccess := teamRead.OrganizationAccess + + options := TeamUpdateOptions{ + OrganizationAccess: &OrganizationAccessOptions{ + // **Note: AccessSecretTeams requires at least one granular permission to be set + // for it to be set, and ManageTeams requires ManageMembership.** + ManageMembership: Bool(true), + ManageTeams: Bool(true), + AccessSecretTeams: Bool(true), + }, + } + + tm, err := client.Teams.Update(ctx, tmTest.ID, options) + require.NoError(t, err) + assert.True(t, tm.OrganizationAccess.ManageMembership) + assert.True(t, tm.OrganizationAccess.ManageTeams) + assert.True(t, tm.OrganizationAccess.AccessSecretTeams) + + refreshed, err := client.Teams.Read(ctx, tmTest.ID) + require.NoError(t, err) + assert.True(t, refreshed.OrganizationAccess.ManageMembership) + assert.True(t, refreshed.OrganizationAccess.ManageTeams) + assert.True(t, refreshed.OrganizationAccess.AccessSecretTeams) + + // Check that other org access fields are not updated + originalTeamAccess.ManageMembership = true + originalTeamAccess.ManageTeams = true + originalTeamAccess.AccessSecretTeams = true + assert.Equal(t, originalTeamAccess, refreshed.OrganizationAccess) +}