From 86a6dfdea9c26799819b2f8992b8ed9a1c47bdea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Luiz=20Vieira?= Date: Sat, 15 Jan 2022 12:12:42 -0300 Subject: [PATCH 01/10] added auth0_prompt_custom_text --- .github/labeler.yml | 92 ++++++----- auth0/provider.go | 1 + auth0/resource_auth0_prompt_custom_text.go | 151 ++++++++++++++++++ .../resource_auth0_prompt_custom_text_test.go | 53 ++++++ docs/resources/prompt_custom_text.md | 60 +++++++ 5 files changed, 313 insertions(+), 44 deletions(-) create mode 100644 auth0/resource_auth0_prompt_custom_text.go create mode 100644 auth0/resource_auth0_prompt_custom_text_test.go create mode 100644 docs/resources/prompt_custom_text.md diff --git a/.github/labeler.yml b/.github/labeler.yml index ecc7ab50..18b2cf2e 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -1,87 +1,91 @@ resource/auth0_action: - - '**/*action.go' - - '**/*action_test.go' + - "**/*action.go" + - "**/*action_test.go" resource/auth0_branding: - - '**/*branding.go' - - '**/*branding_test.go' + - "**/*branding.go" + - "**/*branding_test.go" resource/auth0_client: - - '**/*client.go' - - '**/*client_test.go' + - "**/*client.go" + - "**/*client_test.go" resource/auth0_client_grant: - - '**/*client_grant.go' - - '**/*client_grant_test.go' + - "**/*client_grant.go" + - "**/*client_grant_test.go" resource/auth0_connection: - - '**/*connection.go' - - '**/*connection_test.go' + - "**/*connection.go" + - "**/*connection_test.go" resource/auth0_custom_domain: - - '**/*custom_domain.go' - - '**/*custom_domain_test.go' + - "**/*custom_domain.go" + - "**/*custom_domain_test.go" resource/auth0_email: - - '**/*email.go' - - '**/*email_test.go' + - "**/*email.go" + - "**/*email_test.go" resource/auth0_email_template: - - '**/*email_template.go' - - '**/*email_template_test.go' + - "**/*email_template.go" + - "**/*email_template_test.go" resource/auth0_global_client: - - '**/*global_client.go' - - '**/*global_client_test.go' + - "**/*global_client.go" + - "**/*global_client_test.go" resource/auth0_guardian: - - '**/*guardian.go' - - '**/*guardian_test.go' + - "**/*guardian.go" + - "**/*guardian_test.go" resource/auth0_hook: - - '**/*hook.go' - - '**/*hook_test.go' + - "**/*hook.go" + - "**/*hook_test.go" resource/auth0_log_stream: - - '**/*log_stream.go' - - '**/*log_stream_test.go' + - "**/*log_stream.go" + - "**/*log_stream_test.go" resource/auth0_organization: - - '**/*organization.go' - - '**/*organization_test.go' + - "**/*organization.go" + - "**/*organization_test.go" resource/auth0_prompt: - - '**/*prompt.go' - - '**/*prompt_test.go' + - "**/*prompt.go" + - "**/*prompt_test.go" + +resource/auth0_prompt_custom_text: + - "**/*prompt_custom_text.go" + - "**/*prompt_custom_text_test.go" resource/auth0_resource_server: - - '**/*resource_server.go' - - '**/*resource_server_test.go' + - "**/*resource_server.go" + - "**/*resource_server_test.go" resource/auth0_role: - - '**/*role.go' - - '**/*role_test.go' + - "**/*role.go" + - "**/*role_test.go" resource/auth0_rule: - - '**/*rule.go' - - '**/*rule_test.go' + - "**/*rule.go" + - "**/*rule_test.go" resource/auth0_rule_config: - - '**/*rule_config.go' - - '**/*rule_config_test.go' + - "**/*rule_config.go" + - "**/*rule_config_test.go" resource/auth0_tenant: - - '**/*tenant.go' - - '**/*tenant_test.go' + - "**/*tenant.go" + - "**/*tenant_test.go" resource/auth0_trigger_binding: - - '**/*trigger_binding.go' - - '**/*trigger_binding_test.go' + - "**/*trigger_binding.go" + - "**/*trigger_binding_test.go" resource/auth0_user: - - '**/*user.go' - - '**/*user_test.go' + - "**/*user.go" + - "**/*user_test.go" resource_data: - - '**/resource_data.go' - - '**/resource_data_test.go' \ No newline at end of file + - "**/resource_data.go" + - "**/resource_data_test.go" diff --git a/auth0/provider.go b/auth0/provider.go index cfc90998..2a86615b 100644 --- a/auth0/provider.go +++ b/auth0/provider.go @@ -56,6 +56,7 @@ func init() { "auth0_rule_config": newRuleConfig(), "auth0_hook": newHook(), "auth0_prompt": newPrompt(), + "auth0_prompt_custom_text": newPromptCustomText(), "auth0_email": newEmail(), "auth0_email_template": newEmailTemplate(), "auth0_user": newUser(), diff --git a/auth0/resource_auth0_prompt_custom_text.go b/auth0/resource_auth0_prompt_custom_text.go new file mode 100644 index 00000000..bac8d136 --- /dev/null +++ b/auth0/resource_auth0_prompt_custom_text.go @@ -0,0 +1,151 @@ +package auth0 + +import ( + "bytes" + "encoding/json" + "fmt" + "net/http" + "strings" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/structure" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + + "gopkg.in/auth0.v5/management" +) + +func newPromptCustomText() *schema.Resource { + + return &schema.Resource{ + + Create: createPromptCustomText, + Read: readPromptCustomText, + Update: updatePromptCustomText, + Delete: deletePromptCustomText, + Importer: &schema.ResourceImporter{ + State: importPromptCustomText, + }, + + Schema: map[string]*schema.Schema{ + "prompt": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "login", "login-id", "login-password", "login-email-verification", "signup", "signup-id", "signup-password", "reset-password", "consent", "mfa-push", + "mfa-otp", "mfa-voice", "mfa-phone", "mfa-webauthn", "mfa-sms", "mfa-email", "mfa-recovery-code", "mfa", "status", "device-flow", "email-verification", + "email-otp-challenge", "organizations", "invitation", "common", + }, false), + }, + "language": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "ar", "bg", "bs", "cs", "da", "de", "el", "en", "es", "et", "fi", "fr", "fr-CA", "fr-FR", "he", "hi", "hr", "hu", "id", "is", "it", + "ja", "ko", "lt", "lv", "nb", "nl", "pl", "pt", "pt-BR", "pt-PT", "ro", "ru", "sk", "sl", "sr", "sv", "th", "tr", "uk", "vi", "zh-CN", "zh-TW", + }, false), + }, + "body": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.ValidateJsonString, + DiffSuppressFunc: structure.SuppressJsonDiff, + }, + }, + } +} + +func importPromptCustomText(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + prompt, language, err := getPromptAndLanguage(d) + d.SetId(d.Id()) + d.Set("prompt", prompt) + d.Set("language", language) + + return []*schema.ResourceData{d}, err +} + +func createPromptCustomText(d *schema.ResourceData, m interface{}) error { + d.SetId(d.Get("prompt").(string) + ":" + d.Get("language").(string)) + return updatePromptCustomText(d, m) +} + +func getPromptAndLanguage(d *schema.ResourceData) (string, string, error) { + if d.Id() == "" { + return "", "", fmt.Errorf("ID cannot be empty") + } + + if !strings.Contains(d.Id(), ":") { + return "", "", fmt.Errorf("ID must be formated as prompt:language") + } + + s := strings.Split(d.Id(), ":") + // Validate that this is an ID by making sure it is size 2 + if len(s) != 2 { + return "", "", fmt.Errorf("ID must have lenght of 2") + } + + return s[0], s[1], nil +} + +func marshalCustomTextBody(b map[string]interface{}) (string, error) { + bodyBytes, err := json.Marshal(b) + if err != nil { + return "", fmt.Errorf("Failed to serialize the custom texts to JSON: %w", err) + } + + var buf bytes.Buffer + if err := json.Indent(&buf, []byte(bodyBytes), "", " "); err != nil { + return "", fmt.Errorf("Failed to format the custom texts JSON: %w", err) + } + return buf.String(), nil +} + +func readPromptCustomText(d *schema.ResourceData, m interface{}) error { + api := m.(*management.Management) + p, err := api.Prompt.CustomText(d.Get("prompt").(string), d.Get("language").(string)) + if err != nil { + if mErr, ok := err.(management.Error); ok { + if mErr.Status() == http.StatusNotFound { + d.SetId("") + return nil + } + } + return err + } + + bodyStr, err := marshalCustomTextBody(p) + if err != nil { + return err + } + + d.Set("body", bodyStr) + return nil +} + +func updatePromptCustomText(d *schema.ResourceData, m interface{}) error { + api := m.(*management.Management) + + prompt, language, err := getPromptAndLanguage(d) + + if err != nil { + return err + } + + if d.Get("body").(string) != "" { + var body map[string]interface{} + if err := json.Unmarshal([]byte(d.Get("body").(string)), &body); err != nil { + return err + } + + err := api.Prompt.SetCustomText(prompt, language, body) + if err != nil { + return err + } + } + + return readPromptCustomText(d, m) +} + +func deletePromptCustomText(d *schema.ResourceData, m interface{}) error { + d.SetId("") + return nil +} diff --git a/auth0/resource_auth0_prompt_custom_text_test.go b/auth0/resource_auth0_prompt_custom_text_test.go new file mode 100644 index 00000000..49b0a434 --- /dev/null +++ b/auth0/resource_auth0_prompt_custom_text_test.go @@ -0,0 +1,53 @@ +package auth0 + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/terraform" +) + +func TestAccPromptCustomText(t *testing.T) { + + resource.Test(t, resource.TestCase{ + Providers: map[string]terraform.ResourceProvider{ + "auth0": Provider(), + }, + Steps: []resource.TestStep{ + { + Config: testAccPromptCustomTextCreate, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("auth0_prompt_custom_text.prompt_custom_text", "prompt", "login"), + resource.TestCheckResourceAttr("auth0_prompt_custom_text.prompt_custom_text", "login", "en"), + resource.TestCheckResourceAttr("auth0_prompt_custom_text.prompt_custom_text", "body", "{\"login\": { \"alertListTitle\": \"Alerts\", \"buttonText\": \"Continue\"}}"), + ), + }, + { + Config: testAccPromptCustomTextUpdate, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("auth0_prompt_custom_text.prompt_custom_text", "prompt", "login"), + resource.TestCheckResourceAttr("auth0_prompt_custom_text.prompt_custom_text", "login", "en"), + resource.TestCheckResourceAttr("auth0_prompt_custom_text.prompt_custom_text", "body", "{\"login\": { \"alertListTitle\": \"Alerts\", \"buttonText\": \"Continue to Login\"}}"), + ), + }, + }, + }) +} + +const testAccPromptCustomTextCreate = ` + +resource "auth0_prompt_custom_text" "prompt_custom_text" { + prompt = "login" + language = "en" + body = "{\"login\": { \"alertListTitle\": \"Alerts\", \"buttonText\": \"Continue\"}}"" +} +` + +const testAccPromptCustomTextUpdate = ` + +resource "auth0_prompt_custom_text" "prompt_custom_text" { + prompt = "login" + language = "en" + body = "{\"login\": { \"alertListTitle\": \"Alerts\", \"buttonText\": \"Continue to Login\"}}"" + } + ` diff --git a/docs/resources/prompt_custom_text.md b/docs/resources/prompt_custom_text.md new file mode 100644 index 00000000..388e5884 --- /dev/null +++ b/docs/resources/prompt_custom_text.md @@ -0,0 +1,60 @@ +--- +layout: "auth0" +page_title: "Auth0: auth0_prompt_custom_text" +description: |- + With this resource, you can manage your Auth0 prompts custom text. +--- + +# auth0_prompt_custom_text + +With this resource, you can manage your Auth0 prompts custom text. You can read more about custom texts [here](https://auth0.com/docs/customize/universal-login-pages/customize-login-text-prompts). + +## Example Usage + +```hcl +resource "auth0_prompt_custom_text" "example" { + prompt = "login" + language = "en" + body = < Date: Sat, 15 Jan 2022 12:20:24 -0300 Subject: [PATCH 02/10] rollback formatting --- .github/labeler.yml | 92 ++++++++++++++++++++++----------------------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/.github/labeler.yml b/.github/labeler.yml index 18b2cf2e..b08ebf65 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -1,91 +1,91 @@ resource/auth0_action: - - "**/*action.go" - - "**/*action_test.go" + - '**/*action.go' + - '**/*action_test.go' resource/auth0_branding: - - "**/*branding.go" - - "**/*branding_test.go" + - '**/*branding.go' + - '**/*branding_test.go' resource/auth0_client: - - "**/*client.go" - - "**/*client_test.go" + - '**/*client.go' + - '**/*client_test.go' resource/auth0_client_grant: - - "**/*client_grant.go" - - "**/*client_grant_test.go" + - '**/*client_grant.go' + - '**/*client_grant_test.go' resource/auth0_connection: - - "**/*connection.go" - - "**/*connection_test.go" + - '**/*connection.go' + - '**/*connection_test.go' resource/auth0_custom_domain: - - "**/*custom_domain.go" - - "**/*custom_domain_test.go" + - '**/*custom_domain.go' + - '**/*custom_domain_test.go' resource/auth0_email: - - "**/*email.go" - - "**/*email_test.go" + - '**/*email.go' + - '**/*email_test.go' resource/auth0_email_template: - - "**/*email_template.go" - - "**/*email_template_test.go" + - '**/*email_template.go' + - '**/*email_template_test.go' resource/auth0_global_client: - - "**/*global_client.go" - - "**/*global_client_test.go" + - '**/*global_client.go' + - '**/*global_client_test.go' resource/auth0_guardian: - - "**/*guardian.go" - - "**/*guardian_test.go" + - '**/*guardian.go' + - '**/*guardian_test.go' resource/auth0_hook: - - "**/*hook.go" - - "**/*hook_test.go" + - '**/*hook.go' + - '**/*hook_test.go' resource/auth0_log_stream: - - "**/*log_stream.go" - - "**/*log_stream_test.go" + - '**/*log_stream.go' + - '**/*log_stream_test.go' resource/auth0_organization: - - "**/*organization.go" - - "**/*organization_test.go" + - '**/*organization.go' + - '**/*organization_test.go' resource/auth0_prompt: - - "**/*prompt.go" - - "**/*prompt_test.go" + - '**/*prompt.go' + - '**/*prompt_test.go' resource/auth0_prompt_custom_text: - - "**/*prompt_custom_text.go" - - "**/*prompt_custom_text_test.go" + - '**/*prompt_custom_text.go' + - '**/*prompt_custom_text_test.go' resource/auth0_resource_server: - - "**/*resource_server.go" - - "**/*resource_server_test.go" + - '**/*resource_server.go' + - '**/*resource_server_test.go' resource/auth0_role: - - "**/*role.go" - - "**/*role_test.go" + - '**/*role.go' + - '**/*role_test.go' resource/auth0_rule: - - "**/*rule.go" - - "**/*rule_test.go" + - '**/*rule.go' + - '**/*rule_test.go' resource/auth0_rule_config: - - "**/*rule_config.go" - - "**/*rule_config_test.go" + - '**/*rule_config.go' + - '**/*rule_config_test.go' resource/auth0_tenant: - - "**/*tenant.go" - - "**/*tenant_test.go" + - '**/*tenant.go' + - '**/*tenant_test.go' resource/auth0_trigger_binding: - - "**/*trigger_binding.go" - - "**/*trigger_binding_test.go" + - '**/*trigger_binding.go' + - '**/*trigger_binding_test.go' resource/auth0_user: - - "**/*user.go" - - "**/*user_test.go" + - '**/*user.go' + - '**/*user_test.go' resource_data: - - "**/resource_data.go" - - "**/resource_data_test.go" + - '**/resource_data.go' + - '**/resource_data_test.go' \ No newline at end of file From 216f7200069d6563d7bc441293dc7b4ccf6684c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Luiz=20Vieira?= Date: Sat, 15 Jan 2022 13:06:25 -0300 Subject: [PATCH 03/10] fixing test --- .../resource_auth0_prompt_custom_text_test.go | 32 +++++++++++++------ 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/auth0/resource_auth0_prompt_custom_text_test.go b/auth0/resource_auth0_prompt_custom_text_test.go index 49b0a434..98f8abf1 100644 --- a/auth0/resource_auth0_prompt_custom_text_test.go +++ b/auth0/resource_auth0_prompt_custom_text_test.go @@ -18,16 +18,16 @@ func TestAccPromptCustomText(t *testing.T) { Config: testAccPromptCustomTextCreate, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("auth0_prompt_custom_text.prompt_custom_text", "prompt", "login"), - resource.TestCheckResourceAttr("auth0_prompt_custom_text.prompt_custom_text", "login", "en"), - resource.TestCheckResourceAttr("auth0_prompt_custom_text.prompt_custom_text", "body", "{\"login\": { \"alertListTitle\": \"Alerts\", \"buttonText\": \"Continue\"}}"), + resource.TestCheckResourceAttr("auth0_prompt_custom_text.prompt_custom_text", "language", "en"), + resource.TestCheckResourceAttr("auth0_prompt_custom_text.prompt_custom_text", "body", "{\n \"login\": {\n \"alertListTitle\": \"Alerts\",\n \"buttonText\": \"Continue\",\n \"emailPlaceholder\": \"Email address\"\n }\n}"), ), }, { Config: testAccPromptCustomTextUpdate, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("auth0_prompt_custom_text.prompt_custom_text", "prompt", "login"), - resource.TestCheckResourceAttr("auth0_prompt_custom_text.prompt_custom_text", "login", "en"), - resource.TestCheckResourceAttr("auth0_prompt_custom_text.prompt_custom_text", "body", "{\"login\": { \"alertListTitle\": \"Alerts\", \"buttonText\": \"Continue to Login\"}}"), + resource.TestCheckResourceAttr("auth0_prompt_custom_text.prompt_custom_text", "language", "en"), + resource.TestCheckResourceAttr("auth0_prompt_custom_text.prompt_custom_text", "body", "{\n \"login\": {\n \"alertListTitle\": \"Alerts\",\n \"buttonText\": \"Continue\",\n \"emailPlaceholder\": \"Email address\"\n }\n}"), ), }, }, @@ -39,15 +39,29 @@ const testAccPromptCustomTextCreate = ` resource "auth0_prompt_custom_text" "prompt_custom_text" { prompt = "login" language = "en" - body = "{\"login\": { \"alertListTitle\": \"Alerts\", \"buttonText\": \"Continue\"}}"" + body = < Date: Wed, 19 Jan 2022 20:32:25 +0100 Subject: [PATCH 04/10] Fix small typos on prompt custom text docs --- docs/resources/prompt_custom_text.md | 60 ++++++++++++++-------------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/docs/resources/prompt_custom_text.md b/docs/resources/prompt_custom_text.md index 388e5884..25e860ba 100644 --- a/docs/resources/prompt_custom_text.md +++ b/docs/resources/prompt_custom_text.md @@ -2,12 +2,13 @@ layout: "auth0" page_title: "Auth0: auth0_prompt_custom_text" description: |- - With this resource, you can manage your Auth0 prompts custom text. + With this resource, you can manage custom texts on your Auth0 prompts. --- # auth0_prompt_custom_text -With this resource, you can manage your Auth0 prompts custom text. You can read more about custom texts [here](https://auth0.com/docs/customize/universal-login-pages/customize-login-text-prompts). +With this resource, you can manage custom text on your Auth0 prompts. You can read more about custom texts +[here](https://auth0.com/docs/customize/universal-login-pages/customize-login-text-prompts). ## Example Usage @@ -15,31 +16,31 @@ With this resource, you can manage your Auth0 prompts custom text. You can read resource "auth0_prompt_custom_text" "example" { prompt = "login" language = "en" - body = < Date: Wed, 19 Jan 2022 20:32:36 +0100 Subject: [PATCH 05/10] Refactor prompt custom text --- auth0/resource_auth0_prompt_custom_text.go | 115 ++++++++++-------- .../resource_auth0_prompt_custom_text_test.go | 51 ++++---- 2 files changed, 90 insertions(+), 76 deletions(-) diff --git a/auth0/resource_auth0_prompt_custom_text.go b/auth0/resource_auth0_prompt_custom_text.go index bac8d136..9075c14a 100644 --- a/auth0/resource_auth0_prompt_custom_text.go +++ b/auth0/resource_auth0_prompt_custom_text.go @@ -14,10 +14,24 @@ import ( "gopkg.in/auth0.v5/management" ) -func newPromptCustomText() *schema.Resource { +var ( + availablePrompts = []string{ + "login", "login-id", "login-password", "login-email-verification", "signup", "signup-id", "signup-password", + "reset-password", "consent", "mfa-push", "mfa-otp", "mfa-voice", "mfa-phone", "mfa-webauthn", "mfa-sms", + "mfa-email", "mfa-recovery-code", "mfa", "status", "device-flow", "email-verification", "email-otp-challenge", + "organizations", "invitation", "common", + } + availableLanguages = []string{ + "ar", "bg", "bs", "cs", "da", "de", "el", "en", "es", "et", "fi", "fr", "fr-CA", "fr-FR", "he", "hi", "hr", + "hu", "id", "is", "it", "ja", "ko", "lt", "lv", "nb", "nl", "pl", "pt", "pt-BR", "pt-PT", "ro", "ru", "sk", + "sl", "sr", "sv", "th", "tr", "uk", "vi", "zh-CN", "zh-TW", + } + errEmptyPromptCustomTextID = fmt.Errorf("ID cannot be empty") + errInvalidPromptCustomTextIDFormat = fmt.Errorf("ID must be formated as prompt:language") +) +func newPromptCustomText() *schema.Resource { return &schema.Resource{ - Create: createPromptCustomText, Read: readPromptCustomText, Update: updatePromptCustomText, @@ -25,37 +39,30 @@ func newPromptCustomText() *schema.Resource { Importer: &schema.ResourceImporter{ State: importPromptCustomText, }, - Schema: map[string]*schema.Schema{ "prompt": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - "login", "login-id", "login-password", "login-email-verification", "signup", "signup-id", "signup-password", "reset-password", "consent", "mfa-push", - "mfa-otp", "mfa-voice", "mfa-phone", "mfa-webauthn", "mfa-sms", "mfa-email", "mfa-recovery-code", "mfa", "status", "device-flow", "email-verification", - "email-otp-challenge", "organizations", "invitation", "common", - }, false), + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice(availablePrompts, false), }, "language": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - "ar", "bg", "bs", "cs", "da", "de", "el", "en", "es", "et", "fi", "fr", "fr-CA", "fr-FR", "he", "hi", "hr", "hu", "id", "is", "it", - "ja", "ko", "lt", "lv", "nb", "nl", "pl", "pt", "pt-BR", "pt-PT", "ro", "ru", "sk", "sl", "sr", "sv", "th", "tr", "uk", "vi", "zh-CN", "zh-TW", - }, false), + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice(availableLanguages, false), }, "body": { Type: schema.TypeString, Required: true, - ValidateFunc: validation.ValidateJsonString, + ValidateFunc: validation.StringIsJSON, DiffSuppressFunc: structure.SuppressJsonDiff, }, }, } } -func importPromptCustomText(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { +func importPromptCustomText(d *schema.ResourceData, _ interface{}) ([]*schema.ResourceData, error) { prompt, language, err := getPromptAndLanguage(d) + d.SetId(d.Id()) d.Set("prompt", prompt) d.Set("language", language) @@ -68,40 +75,9 @@ func createPromptCustomText(d *schema.ResourceData, m interface{}) error { return updatePromptCustomText(d, m) } -func getPromptAndLanguage(d *schema.ResourceData) (string, string, error) { - if d.Id() == "" { - return "", "", fmt.Errorf("ID cannot be empty") - } - - if !strings.Contains(d.Id(), ":") { - return "", "", fmt.Errorf("ID must be formated as prompt:language") - } - - s := strings.Split(d.Id(), ":") - // Validate that this is an ID by making sure it is size 2 - if len(s) != 2 { - return "", "", fmt.Errorf("ID must have lenght of 2") - } - - return s[0], s[1], nil -} - -func marshalCustomTextBody(b map[string]interface{}) (string, error) { - bodyBytes, err := json.Marshal(b) - if err != nil { - return "", fmt.Errorf("Failed to serialize the custom texts to JSON: %w", err) - } - - var buf bytes.Buffer - if err := json.Indent(&buf, []byte(bodyBytes), "", " "); err != nil { - return "", fmt.Errorf("Failed to format the custom texts JSON: %w", err) - } - return buf.String(), nil -} - func readPromptCustomText(d *schema.ResourceData, m interface{}) error { api := m.(*management.Management) - p, err := api.Prompt.CustomText(d.Get("prompt").(string), d.Get("language").(string)) + customText, err := api.Prompt.CustomText(d.Get("prompt").(string), d.Get("language").(string)) if err != nil { if mErr, ok := err.(management.Error); ok { if mErr.Status() == http.StatusNotFound { @@ -112,20 +88,18 @@ func readPromptCustomText(d *schema.ResourceData, m interface{}) error { return err } - bodyStr, err := marshalCustomTextBody(p) + body, err := marshalCustomTextBody(customText) if err != nil { return err } - d.Set("body", bodyStr) + d.Set("body", body) return nil } func updatePromptCustomText(d *schema.ResourceData, m interface{}) error { api := m.(*management.Management) - prompt, language, err := getPromptAndLanguage(d) - if err != nil { return err } @@ -149,3 +123,36 @@ func deletePromptCustomText(d *schema.ResourceData, m interface{}) error { d.SetId("") return nil } + +func getPromptAndLanguage(d *schema.ResourceData) (string, string, error) { + rawID := d.Id() + if rawID == "" { + return "", "", errEmptyPromptCustomTextID + } + + if !strings.Contains(rawID, ":") { + return "", "", errInvalidPromptCustomTextIDFormat + } + + idPair := strings.Split(rawID, ":") + if len(idPair) != 2 { + return "", "", errInvalidPromptCustomTextIDFormat + } + + return idPair[0], idPair[1], nil +} + +func marshalCustomTextBody(b map[string]interface{}) (string, error) { + bodyBytes, err := json.Marshal(b) + if err != nil { + return "", fmt.Errorf("Failed to serialize the custom texts to JSON: %w", err) + } + + var buffer bytes.Buffer + const jsonIndentation = " " + if err := json.Indent(&buffer, bodyBytes, "", jsonIndentation); err != nil { + return "", fmt.Errorf("Failed to format the custom texts JSON: %w", err) + } + + return buffer.String(), nil +} diff --git a/auth0/resource_auth0_prompt_custom_text_test.go b/auth0/resource_auth0_prompt_custom_text_test.go index 98f8abf1..63798a47 100644 --- a/auth0/resource_auth0_prompt_custom_text_test.go +++ b/auth0/resource_auth0_prompt_custom_text_test.go @@ -8,7 +8,6 @@ import ( ) func TestAccPromptCustomText(t *testing.T) { - resource.Test(t, resource.TestCase{ Providers: map[string]terraform.ResourceProvider{ "auth0": Provider(), @@ -19,7 +18,11 @@ func TestAccPromptCustomText(t *testing.T) { Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("auth0_prompt_custom_text.prompt_custom_text", "prompt", "login"), resource.TestCheckResourceAttr("auth0_prompt_custom_text.prompt_custom_text", "language", "en"), - resource.TestCheckResourceAttr("auth0_prompt_custom_text.prompt_custom_text", "body", "{\n \"login\": {\n \"alertListTitle\": \"Alerts\",\n \"buttonText\": \"Continue\",\n \"emailPlaceholder\": \"Email address\"\n }\n}"), + resource.TestCheckResourceAttr( + "auth0_prompt_custom_text.prompt_custom_text", + "body", + "{\n \"login\": {\n \"alertListTitle\": \"Alerts\",\n \"buttonText\": \"Continue\",\n \"emailPlaceholder\": \"Email address\"\n }\n}", + ), ), }, { @@ -27,7 +30,11 @@ func TestAccPromptCustomText(t *testing.T) { Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("auth0_prompt_custom_text.prompt_custom_text", "prompt", "login"), resource.TestCheckResourceAttr("auth0_prompt_custom_text.prompt_custom_text", "language", "en"), - resource.TestCheckResourceAttr("auth0_prompt_custom_text.prompt_custom_text", "body", "{\n \"login\": {\n \"alertListTitle\": \"Alerts\",\n \"buttonText\": \"Continue\",\n \"emailPlaceholder\": \"Email address\"\n }\n}"), + resource.TestCheckResourceAttr( + "auth0_prompt_custom_text.prompt_custom_text", + "body", + "{\n \"login\": {\n \"alertListTitle\": \"Alerts\",\n \"buttonText\": \"Proceed\",\n \"emailPlaceholder\": \"Email Address\"\n }\n}", + ), ), }, }, @@ -35,33 +42,33 @@ func TestAccPromptCustomText(t *testing.T) { } const testAccPromptCustomTextCreate = ` - resource "auth0_prompt_custom_text" "prompt_custom_text" { prompt = "login" language = "en" - body = < Date: Wed, 19 Jan 2022 17:39:13 -0300 Subject: [PATCH 06/10] added delete to clear body --- auth0/resource_auth0_prompt_custom_text.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/auth0/resource_auth0_prompt_custom_text.go b/auth0/resource_auth0_prompt_custom_text.go index 9075c14a..ab2fd5a1 100644 --- a/auth0/resource_auth0_prompt_custom_text.go +++ b/auth0/resource_auth0_prompt_custom_text.go @@ -26,7 +26,7 @@ var ( "hu", "id", "is", "it", "ja", "ko", "lt", "lv", "nb", "nl", "pl", "pt", "pt-BR", "pt-PT", "ro", "ru", "sk", "sl", "sr", "sv", "th", "tr", "uk", "vi", "zh-CN", "zh-TW", } - errEmptyPromptCustomTextID = fmt.Errorf("ID cannot be empty") + errEmptyPromptCustomTextID = fmt.Errorf("ID cannot be empty") errInvalidPromptCustomTextIDFormat = fmt.Errorf("ID must be formated as prompt:language") ) @@ -121,6 +121,7 @@ func updatePromptCustomText(d *schema.ResourceData, m interface{}) error { func deletePromptCustomText(d *schema.ResourceData, m interface{}) error { d.SetId("") + d.Set("body", "{}") return nil } From 4ecebb51e915c567b9e15020190d1ec43aea9c92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Luiz=20Vieira?= Date: Wed, 19 Jan 2022 18:23:08 -0300 Subject: [PATCH 07/10] added update on delete --- auth0/resource_auth0_prompt_custom_text.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/auth0/resource_auth0_prompt_custom_text.go b/auth0/resource_auth0_prompt_custom_text.go index ab2fd5a1..612a07ed 100644 --- a/auth0/resource_auth0_prompt_custom_text.go +++ b/auth0/resource_auth0_prompt_custom_text.go @@ -120,8 +120,11 @@ func updatePromptCustomText(d *schema.ResourceData, m interface{}) error { } func deletePromptCustomText(d *schema.ResourceData, m interface{}) error { - d.SetId("") d.Set("body", "{}") + + updatePromptCustomText(d, m) + + d.SetId("") return nil } From e2560408e1014d0d1a2e855ad1c1eacf69f73a82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Luiz=20Vieira?= Date: Wed, 19 Jan 2022 19:31:40 -0300 Subject: [PATCH 08/10] Update auth0/resource_auth0_prompt_custom_text.go edded error Co-authored-by: Sergiu Ghitea <28300158+sergiughf@users.noreply.github.com> --- auth0/resource_auth0_prompt_custom_text.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/auth0/resource_auth0_prompt_custom_text.go b/auth0/resource_auth0_prompt_custom_text.go index 612a07ed..62f82c97 100644 --- a/auth0/resource_auth0_prompt_custom_text.go +++ b/auth0/resource_auth0_prompt_custom_text.go @@ -122,7 +122,9 @@ func updatePromptCustomText(d *schema.ResourceData, m interface{}) error { func deletePromptCustomText(d *schema.ResourceData, m interface{}) error { d.Set("body", "{}") - updatePromptCustomText(d, m) + if err := updatePromptCustomText(d, m); err != nil { + return err + } d.SetId("") return nil From f017f3ec2156148e7b9c2799bab0f12e0962fa85 Mon Sep 17 00:00:00 2001 From: Sergiu Ghitea Date: Thu, 20 Jan 2022 09:46:33 +0100 Subject: [PATCH 09/10] Improve error handling when importing prompt custom text --- auth0/resource_auth0_prompt_custom_text.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/auth0/resource_auth0_prompt_custom_text.go b/auth0/resource_auth0_prompt_custom_text.go index 62f82c97..0ffeceb0 100644 --- a/auth0/resource_auth0_prompt_custom_text.go +++ b/auth0/resource_auth0_prompt_custom_text.go @@ -62,12 +62,15 @@ func newPromptCustomText() *schema.Resource { func importPromptCustomText(d *schema.ResourceData, _ interface{}) ([]*schema.ResourceData, error) { prompt, language, err := getPromptAndLanguage(d) + if err != nil { + return []*schema.ResourceData{}, err + } d.SetId(d.Id()) d.Set("prompt", prompt) d.Set("language", language) - return []*schema.ResourceData{d}, err + return []*schema.ResourceData{d}, nil } func createPromptCustomText(d *schema.ResourceData, m interface{}) error { From d550a430cb3e70ccc111db5076a42070c2bb0721 Mon Sep 17 00:00:00 2001 From: Sergiu Ghitea Date: Thu, 20 Jan 2022 09:50:09 +0100 Subject: [PATCH 10/10] Add CHANGELOG for prompt custom text --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 663a714a..0f6c9c7a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.26.0 + +ENHANCEMENTS: + +* **New Resource:** `auth0_prompt_custom_text` ([#497](https://github.com/alexkappa/terraform-provider-auth0/pull/497)) + ## 0.25.1 ENHANCEMENTS: