Skip to content

Commit

Permalink
Fix infinite plan on user metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
sergiught committed Jul 19, 2022
1 parent 4de639b commit 6f2b50e
Show file tree
Hide file tree
Showing 5 changed files with 499 additions and 216 deletions.
49 changes: 40 additions & 9 deletions auth0/resource_auth0_user.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,9 @@ func readUser(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D
api := m.(*management.Management)
user, err := api.User.Read(d.Id())
if err != nil {
if mErr, ok := err.(management.Error); ok {
if mErr.Status() == http.StatusNotFound {
d.SetId("")
return nil
}
if err, ok := err.(management.Error); ok && err.Status() == http.StatusNotFound {
d.SetId("")
return nil
}
return diag.FromErr(err)
}
Expand Down Expand Up @@ -250,21 +248,54 @@ func expandUser(d *schema.ResourceData) (*management.User, error) {
Blocked: Bool(d, "blocked"),
}

userMeta, err := JSON(d, "user_metadata")
userMetadata, err := expandMetadata(d, "user")
if err != nil {
return nil, err
}
user.UserMetadata = &userMeta
user.UserMetadata = &userMetadata

appMeta, err := JSON(d, "app_metadata")
appMetadata, err := expandMetadata(d, "app")
if err != nil {
return nil, err
}
user.AppMetadata = &appMeta
user.AppMetadata = &appMetadata

return user, nil
}

func expandMetadata(d *schema.ResourceData, metadataType string) (map[string]interface{}, error) {
if !d.HasChange(metadataType + "_metadata") {
return map[string]interface{}{}, nil
}

oldMetadata, newMetadata := d.GetChange(metadataType + "_metadata")
if oldMetadata == "" {
return JSON(d, metadataType+"_metadata")
}

if newMetadata == "" || newMetadata == nil {
return map[string]interface{}{}, nil
}

oldMap, err := structure.ExpandJsonFromString(oldMetadata.(string))
if err != nil {
return map[string]interface{}{}, err
}

newMap, err := structure.ExpandJsonFromString(newMetadata.(string))
if err != nil {
return map[string]interface{}{}, err
}

for key := range oldMap {
if _, ok := newMap[key]; !ok {
newMap[key] = nil
}
}

return newMap, nil
}

func flattenUserRoles(roleList *management.RoleList) []interface{} {
var roles []interface{}
for _, role := range roleList.Roles {
Expand Down
102 changes: 59 additions & 43 deletions auth0/resource_auth0_user_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,22 +75,18 @@ resource auth0_user user {
family_name = "Lastname"
nickname = "{{.testName}}"
picture = "https://www.example.com/picture.jpg"
user_metadata = <<EOF
{
"foo": "bar",
"bar": { "baz": "qux" }
}
EOF
app_metadata = <<EOF
{
"foo": "bar",
"bar": { "baz": "qux" }
}
EOF
user_metadata = jsonencode({
"foo": "bar",
"baz": "qux"
})
app_metadata = jsonencode({
"foo": "bar",
"baz": "qux"
})
}
`

const testAccUserAddRole = `
const testAccUserUpdate = `
resource auth0_user user {
depends_on = [auth0_role.owner, auth0_role.admin]
connection_name = "Username-Password-Authentication"
Expand All @@ -104,18 +100,12 @@ resource auth0_user user {
nickname = "{{.testName}}"
picture = "https://www.example.com/picture.jpg"
roles = [ auth0_role.owner.id, auth0_role.admin.id ]
user_metadata = <<EOF
{
"foo": "bar",
"bar": { "baz": "qux" }
}
EOF
app_metadata = <<EOF
{
"foo": "bar",
"bar": { "baz": "qux" }
}
EOF
user_metadata = jsonencode({
"foo": "bars",
})
app_metadata = jsonencode({
"foo": "bars",
})
}
resource auth0_role owner {
Expand All @@ -130,7 +120,7 @@ resource auth0_role admin {
}
`

const testAccUserRemoveRole = `
const testAccUserUpdateAgain = `
resource auth0_user user {
depends_on = [auth0_role.admin]
connection_name = "Username-Password-Authentication"
Expand All @@ -144,18 +134,14 @@ resource auth0_user user {
nickname = "{{.testName}}"
picture = "https://www.example.com/picture.jpg"
roles = [ auth0_role.admin.id ]
user_metadata = <<EOF
{
"foo": "bar",
"bar": { "baz": "qux" }
}
EOF
app_metadata = <<EOF
{
"foo": "bar",
"bar": { "baz": "qux" }
}
EOF
user_metadata = jsonencode({
"foo": "barss",
"foo2": "bar2",
})
app_metadata = jsonencode({
"foo": "barss",
"foo2": "bar2",
})
}
resource auth0_role admin {
Expand All @@ -164,6 +150,21 @@ resource auth0_role admin {
}
`

const testAccUserUpdateAgainAndAgain = `
resource auth0_user user {
connection_name = "Username-Password-Authentication"
username = "{{.testName}}"
user_id = "{{.testName}}"
email = "{{.testName}}@acceptance.test.com"
password = "passpass$12$12"
name = "Firstname Lastname"
given_name = "Firstname"
family_name = "Lastname"
nickname = "{{.testName}}"
picture = "https://www.example.com/picture.jpg"
}
`

func TestAccUser(t *testing.T) {
httpRecorder := configureHTTPRecorder(t)

Expand All @@ -173,29 +174,44 @@ func TestAccUser(t *testing.T) {
{
Config: template.ParseTestName(testAccUserCreate, strings.ToLower(t.Name())),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("auth0_user.user", "connection_name", "Username-Password-Authentication"),
resource.TestCheckResourceAttr("auth0_user.user", "username", strings.ToLower(t.Name())),
resource.TestCheckResourceAttr("auth0_user.user", "user_id", fmt.Sprintf("auth0|%s", strings.ToLower(t.Name()))),
resource.TestCheckResourceAttr("auth0_user.user", "email", fmt.Sprintf("%s@acceptance.test.com", strings.ToLower(t.Name()))),
resource.TestCheckResourceAttr("auth0_user.user", "name", "Firstname Lastname"),
resource.TestCheckResourceAttr("auth0_user.user", "family_name", "Lastname"),
resource.TestCheckResourceAttr("auth0_user.user", "given_name", "Firstname"),
resource.TestCheckResourceAttr("auth0_user.user", "family_name", "Lastname"),
resource.TestCheckResourceAttr("auth0_user.user", "nickname", strings.ToLower(t.Name())),
resource.TestCheckResourceAttr("auth0_user.user", "connection_name", "Username-Password-Authentication"),
resource.TestCheckResourceAttr("auth0_user.user", "roles.#", "0"),
resource.TestCheckResourceAttr("auth0_user.user", "picture", "https://www.example.com/picture.jpg"),
resource.TestCheckResourceAttr("auth0_user.user", "user_metadata", `{"baz":"qux","foo":"bar"}`),
resource.TestCheckResourceAttr("auth0_user.user", "app_metadata", `{"baz":"qux","foo":"bar"}`),
resource.TestCheckResourceAttr("auth0_user.user", "roles.#", "0"),
),
},
{
Config: template.ParseTestName(testAccUserAddRole, strings.ToLower(t.Name())),
Config: template.ParseTestName(testAccUserUpdate, strings.ToLower(t.Name())),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("auth0_user.user", "roles.#", "2"),
resource.TestCheckResourceAttr("auth0_role.owner", "name", "owner"),
resource.TestCheckResourceAttr("auth0_role.admin", "name", "admin"),
resource.TestCheckResourceAttr("auth0_user.user", "user_metadata", `{"foo":"bars"}`),
resource.TestCheckResourceAttr("auth0_user.user", "app_metadata", `{"foo":"bars"}`),
),
},
{
Config: template.ParseTestName(testAccUserRemoveRole, strings.ToLower(t.Name())),
Config: template.ParseTestName(testAccUserUpdateAgain, strings.ToLower(t.Name())),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("auth0_user.user", "roles.#", "1"),
resource.TestCheckResourceAttr("auth0_user.user", "user_metadata", `{"foo":"barss","foo2":"bar2"}`),
resource.TestCheckResourceAttr("auth0_user.user", "app_metadata", `{"foo":"barss","foo2":"bar2"}`),
),
},
{
Config: template.ParseTestName(testAccUserUpdateAgainAndAgain, strings.ToLower(t.Name())),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("auth0_user.user", "roles.#", "0"),
resource.TestCheckResourceAttr("auth0_user.user", "user_metadata", ""),
resource.TestCheckResourceAttr("auth0_user.user", "app_metadata", ""),
),
},
},
Expand Down
Loading

0 comments on commit 6f2b50e

Please sign in to comment.