Skip to content

Commit

Permalink
[3/X] DXCDT-461: Remove permissions field from role resource (#714)
Browse files Browse the repository at this point in the history
Co-authored-by: Will Vedder <willvedd@gmail.com>
  • Loading branch information
sergiught and willvedd authored Jul 13, 2023
1 parent fa1dc13 commit cb94261
Show file tree
Hide file tree
Showing 17 changed files with 2,947 additions and 5,852 deletions.
4 changes: 2 additions & 2 deletions docs/data-sources/role.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ data "auth0_role" "some-role-by-id" {

### Read-Only

- `description` (String) Description of the role.
- `description` (String) The description of the role.
- `id` (String) The ID of this resource.
- `permissions` (Set of Object) Configuration settings for permissions (scopes) attached to the role. Managing permissions through the `permissions` attribute is deprecated and it will be removed in a future major version. Migrate to the `auth0_role_permission` or `auth0_role_permissions` resource to manage role permissions instead. Check the [MIGRATION GUIDE](https://github.com/auth0/terraform-provider-auth0/blob/main/MIGRATION_GUIDE.md#role-permissions) for more info. (see [below for nested schema](#nestedatt--permissions))
- `permissions` (Set of Object) Configuration settings for permissions (scopes) attached to the role. (see [below for nested schema](#nestedatt--permissions))

<a id="nestedatt--permissions"></a>
### Nested Schema for `permissions`
Expand Down
18 changes: 2 additions & 16 deletions docs/resources/role.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,30 +52,16 @@ resource "auth0_role" "my_role" {

### Required

- `name` (String) Name for this role.
- `name` (String) The name of the role.

### Optional

- `description` (String) Description of the role.
- `permissions` (Block Set, Deprecated) Configuration settings for permissions (scopes) attached to the role. Managing permissions through the `permissions` attribute is deprecated and it will be removed in a future major version. Migrate to the `auth0_role_permission` or `auth0_role_permissions` resource to manage role permissions instead. Check the [MIGRATION GUIDE](https://github.com/auth0/terraform-provider-auth0/blob/main/MIGRATION_GUIDE.md#role-permissions) for more info. (see [below for nested schema](#nestedblock--permissions))
- `description` (String) The description of the role.

### Read-Only

- `id` (String) The ID of this resource.

<a id="nestedblock--permissions"></a>
### Nested Schema for `permissions`

Required:

- `name` (String) Name of the permission (scope) configured on the resource server. If referencing a scope from an `auth0_resource_server` resource, use the `value` property, for example `auth0_resource_server.my_resource_server.scopes[0].value`.
- `resource_server_identifier` (String) Unique identifier for the resource server.

Read-Only:

- `description` (String) Description of the permission.
- `resource_server_name` (String) Name of resource server that the permission is associated with.

## Import

Import is supported using the following syntax:
Expand Down
105 changes: 97 additions & 8 deletions internal/auth0/role/data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"

"github.com/auth0/terraform-provider-auth0/internal/auth0"
"github.com/auth0/terraform-provider-auth0/internal/config"
internalSchema "github.com/auth0/terraform-provider-auth0/internal/schema"
)
Expand All @@ -34,34 +33,124 @@ func dataSourceSchema() map[string]*schema.Schema {
dataSourceSchema["name"].Description = "The name of the role. If not provided, `role_id` must be set."
dataSourceSchema["name"].AtLeastOneOf = []string{"role_id", "name"}

dataSourceSchema["permissions"] = &schema.Schema{
Type: schema.TypeSet,
Computed: true,
Description: "Configuration settings for permissions (scopes) attached to the role.",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Computed: true,
Description: "Name of the permission (scope) configured on the resource server (API).",
},
"resource_server_identifier": {
Type: schema.TypeString,
Computed: true,
Description: "Unique identifier for the resource server (API).",
},
"description": {
Type: schema.TypeString,
Computed: true,
Description: "Description of the permission.",
},
"resource_server_name": {
Type: schema.TypeString,
Computed: true,
Description: "Name of resource server (API) that the permission is associated with.",
},
},
},
}

return dataSourceSchema
}

func readRoleForDataSource(ctx context.Context, data *schema.ResourceData, meta interface{}) diag.Diagnostics {
api := meta.(*config.Config).GetAPI()

roleID := data.Get("role_id").(string)
if roleID != "" {
data.SetId(roleID)
return auth0.CheckFor404Error(ctx, readRole, data, meta)
return readRoleByID(ctx, data, api, roleID)
}

api := meta.(*config.Config).GetAPI()
name := data.Get("name").(string)
roleName := data.Get("name").(string)
return readRoleByName(ctx, data, api, roleName)
}

func getAllRolePermissions(
ctx context.Context,
api *management.Management,
roleID string,
) ([]*management.Permission, error) {
var permissions []*management.Permission
var page int
for {
permissionList, err := api.Role.Permissions(ctx, roleID, management.Page(page), management.PerPage(100))
if err != nil {
return nil, err
}

permissions = append(permissions, permissionList.Permissions...)

if !permissionList.HasNext() {
break
}

page++
}

return permissions, nil
}

func readRoleByID(
ctx context.Context,
data *schema.ResourceData,
api *management.Management,
roleID string,
) diag.Diagnostics {
role, err := api.Role.Read(ctx, roleID)
if err != nil {
return diag.FromErr(err)
}

permissions, err := getAllRolePermissions(ctx, api, roleID)
if err != nil {
return diag.FromErr(err)
}

return diag.FromErr(flattenRole(data, role, permissions))
}

func readRoleByName(
ctx context.Context,
data *schema.ResourceData,
api *management.Management,
roleName string,
) diag.Diagnostics {
page := 0
for {
roles, err := api.Role.List(
ctx,
management.Page(page),
management.PerPage(100),
management.Parameter("name_filter", name),
management.Parameter("name_filter", roleName),
)
if err != nil {
return diag.FromErr(err)
}

for _, role := range roles.Roles {
if role.GetName() == name {
if role.GetName() == roleName {
data.SetId(role.GetID())
return auth0.CheckFor404Error(ctx, readRole, data, meta)

permissions, err := getAllRolePermissions(ctx, api, role.GetID())
if err != nil {
return diag.FromErr(err)
}

return diag.FromErr(flattenRole(data, role, permissions))
}
}

Expand All @@ -72,5 +161,5 @@ func readRoleForDataSource(ctx context.Context, data *schema.ResourceData, meta
page++
}

return diag.Errorf("No role found with \"name\" = %q", name)
return diag.Errorf("No role found with \"name\" = %q", roleName)
}
71 changes: 32 additions & 39 deletions internal/auth0/role/data_source_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,27 +38,43 @@ resource "auth0_role" "the_one" {
name = "The One - Acceptance Test - {{.testName}}"
description = "The One - Acceptance Test"
}
permissions {
name = "stop:bullets"
resource "auth0_role_permissions" "role_permissions" {
depends_on = [ auth0_role.the_one ]
role_id = auth0_role.the_one.id
permissions {
resource_server_identifier = auth0_resource_server.matrix.identifier
name = "stop:bullets"
}
permissions {
name = "bring:peace"
permissions {
resource_server_identifier = auth0_resource_server.matrix.identifier
name = "bring:peace"
}
}
`

const testAccDataSourceNonExistentRole = `
data "auth0_role" "test" {
name = "this-role-does-not-exist"
}
`

const testAccDataSourceRoleByName = testAccGivenAResourceServer + `
data "auth0_role" "test" {
depends_on = [ auth0_role_permissions.role_permissions ]
name = auth0_role.the_one.name
}
`

const testAccDataSourceRoleByID = testAccGivenAResourceServer + `
data "auth0_role" "test" {
depends_on = [ auth0_role_permissions.role_permissions ]
role_id = auth0_role.the_one.id
}
`
Expand All @@ -75,58 +91,35 @@ func TestAccDataSourceRoleRequiredArguments(t *testing.T) {
})
}

func TestAccDataSourceRoleByName(t *testing.T) {
func TestAccDataSourceRole(t *testing.T) {
testName := strings.ToLower(t.Name())

acctest.Test(t, resource.TestCase{
PreventPostDestroyRefresh: true,
Steps: []resource.TestStep{
{
Config: acctest.ParseTestName(testAccDataSourceRoleByName, t.Name()),
Config: acctest.ParseTestName(testAccDataSourceNonExistentRole, testName),
ExpectError: regexp.MustCompile(
`No role found with "name" = "this-role-does-not-exist"`,
),
},
{
Config: acctest.ParseTestName(testAccDataSourceRoleByName, testName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckNoResourceAttr("data.auth0_role.test", "role_id"),
resource.TestCheckResourceAttr("data.auth0_role.test", "name", fmt.Sprintf("The One - Acceptance Test - %s", t.Name())),
resource.TestCheckResourceAttr("data.auth0_role.test", "name", fmt.Sprintf("The One - Acceptance Test - %s", testName)),
resource.TestCheckResourceAttr("data.auth0_role.test", "description", "The One - Acceptance Test"),
resource.TestCheckResourceAttr("data.auth0_role.test", "permissions.#", "2"),
),
},
},
})
}

func TestAccDataSourceRoleByID(t *testing.T) {
testName := strings.ToLower(t.Name())

acctest.Test(t, resource.TestCase{
PreventPostDestroyRefresh: true,
Steps: []resource.TestStep{
{
Config: acctest.ParseTestName(testAccDataSourceRoleByID, testName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet("data.auth0_role.test", "role_id"),
resource.TestCheckResourceAttr("data.auth0_role.test", "name", fmt.Sprintf("The One - Acceptance Test - %s", strings.ToLower(t.Name()))),
resource.TestCheckResourceAttr("data.auth0_role.test", "name", fmt.Sprintf("The One - Acceptance Test - %s", testName)),
resource.TestCheckResourceAttr("data.auth0_role.test", "description", "The One - Acceptance Test"),
resource.TestCheckResourceAttr("data.auth0_role.test", "permissions.#", "2"),
),
},
},
})
}

const testAccDataSourceNonexistentRole = `
data "auth0_role" "test" {
name = "this-role-does-not-exist"
}
`

func TestAccDataSourceRoleDoesNotExist(t *testing.T) {
acctest.Test(t, resource.TestCase{
PreventPostDestroyRefresh: true,
Steps: []resource.TestStep{
{
Config: acctest.ParseTestName(testAccDataSourceNonexistentRole, t.Name()),
ExpectError: regexp.MustCompile(
`No role found with "name" = "this-role-does-not-exist"`,
),
},
},
})
}
17 changes: 17 additions & 0 deletions internal/auth0/role/expand.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package role

import (
"github.com/auth0/go-auth0/management"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"

"github.com/auth0/terraform-provider-auth0/internal/value"
)

func expandRole(data *schema.ResourceData) *management.Role {
cfg := data.GetRawConfig()

return &management.Role{
Name: value.String(cfg.GetAttr("name")),
Description: value.String(cfg.GetAttr("description")),
}
}
30 changes: 30 additions & 0 deletions internal/auth0/role/flatten.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package role

import (
"github.com/auth0/go-auth0/management"
"github.com/hashicorp/go-multierror"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func flattenRole(data *schema.ResourceData, role *management.Role, permissions []*management.Permission) error {
result := multierror.Append(
data.Set("name", role.GetName()),
data.Set("description", role.GetDescription()),
data.Set("permissions", flattenRolePermissions(permissions)),
)

return result.ErrorOrNil()
}

func flattenRolePermissions(permissions []*management.Permission) []interface{} {
var result []interface{}
for _, permission := range permissions {
result = append(result, map[string]interface{}{
"name": permission.GetName(),
"description": permission.GetDescription(),
"resource_server_identifier": permission.GetResourceServerIdentifier(),
"resource_server_name": permission.GetResourceServerName(),
})
}
return result
}
Loading

0 comments on commit cb94261

Please sign in to comment.