Skip to content

Commit

Permalink
Merge pull request #2179 from okta/s-nel_2170
Browse files Browse the repository at this point in the history
S nel 2170
  • Loading branch information
duytiennguyen-okta authored Jan 17, 2025
2 parents 177dc1b + d2a704a commit 48f3323
Show file tree
Hide file tree
Showing 11 changed files with 756 additions and 0 deletions.
40 changes: 40 additions & 0 deletions docs/resources/email_template_settings.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
page_title: "Resource: okta_email_template_settings"
description: |-
Manages email template settings
---

# Resource: okta_email_template_settings

Manages email template settings

## Example Usage

```terraform
resource "okta_email_template_settings" "example" {
brand_id = "<brand id>"
template_name = "ForgotPassword"
recipients = "ADMINS_ONLY"
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `brand_id` (String) The ID of the brand.
- `recipients` (String) The recipients the emails of this template will be sent to - Valid values: `ALL_USERS`, `ADMINS_ONLY`, `NO_USERS`
- `template_name` (String) Email template name - Example values: `AccountLockout`,`ADForgotPassword`,`ADForgotPasswordDenied`,`ADSelfServiceUnlock`,`ADUserActivation`,`AuthenticatorEnrolled`,`AuthenticatorReset`,`ChangeEmailConfirmation`,`EmailChallenge`,`EmailChangeConfirmation`,`EmailFactorVerification`,`ForgotPassword`,`ForgotPasswordDenied`,`IGAReviewerEndNotification`,`IGAReviewerNotification`,`IGAReviewerPendingNotification`,`IGAReviewerReassigned`,`LDAPForgotPassword`,`LDAPForgotPasswordDenied`,`LDAPSelfServiceUnlock`,`LDAPUserActivation`,`MyAccountChangeConfirmation`,`NewSignOnNotification`,`OktaVerifyActivation`,`PasswordChanged`,`PasswordResetByAdmin`,`PendingEmailChange`,`RegistrationActivation`,`RegistrationEmailVerification`,`SelfServiceUnlock`,`SelfServiceUnlockOnUnlockedAccount`,`UserActivation`

### Read-Only

- `id` (String) The ID of the resource. This is a compound ID of the brand ID and the template name.

## Import

Import is supported using the following syntax:

```shell
terraform import okta_email_template_settings.example <brand_id>/<template_name>
```
6 changes: 6 additions & 0 deletions examples/resources/okta_email_template_settings/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# okta_email_template_settings

Use this resource to set the [email template settings](https://developer.okta.com/docs/api/openapi/okta-management/management/tag/CustomTemplates/#tag/CustomTemplates/operation/replaceEmailSettings)
of an email template belonging to a brand in an Okta organization.

- Example [basic.tf](./basic.tf)
8 changes: 8 additions & 0 deletions examples/resources/okta_email_template_settings/basic.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
data "okta_brands" "test" {
}

resource "okta_email_template_settings" "test" {
brand_id = tolist(data.okta_brands.test.brands)[0].id
template_name = "UserActivation"
recipients = "NO_USERS"
}
1 change: 1 addition & 0 deletions examples/resources/okta_email_template_settings/import.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
terraform import okta_email_template_settings.example <brand_id>/<template_name>
5 changes: 5 additions & 0 deletions examples/resources/okta_email_template_settings/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
resource "okta_email_template_settings" "example" {
brand_id = "<brand id>"
template_name = "ForgotPassword"
recipients = "ADMINS_ONLY"
}
8 changes: 8 additions & 0 deletions examples/resources/okta_email_template_settings/updated.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
data "okta_brands" "test" {
}

resource "okta_email_template_settings" "test" {
brand_id = tolist(data.okta_brands.test.brands)[0].id
template_name = "UserActivation"
recipients = "ADMINS_ONLY"
}
1 change: 1 addition & 0 deletions okta/framework_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ func (p *FrameworkProvider) Resources(_ context.Context) []func() resource.Resou
NewPreviewSigninResource,
NewGroupOwnerResource,
NewAppSignOnPolicyResource,
NewEmailTemplateSettingsResource,
}
}

Expand Down
169 changes: 169 additions & 0 deletions okta/resource_okta_email_template_settings.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
package okta

import (
"context"
"fmt"

"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/okta/okta-sdk-golang/v4/okta"
)

var (
_ resource.Resource = &emailTemplateSettingsResource{}
_ resource.ResourceWithConfigure = &emailTemplateSettingsResource{}
_ resource.ResourceWithImportState = &emailTemplateSettingsResource{}
)

func NewEmailTemplateSettingsResource() resource.Resource {
return &emailTemplateSettingsResource{}
}

type emailTemplateSettingsResource struct {
*Config
}

type emailTemplateSettingsResourceModel struct {
ID types.String `tfsdk:"id"`
BrandID types.String `tfsdk:"brand_id"`
TemplateName types.String `tfsdk:"template_name"`
Recipients types.String `tfsdk:"recipients"`
}

func (r *emailTemplateSettingsResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_email_template_settings"
}

func (r *emailTemplateSettingsResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = schema.Schema{
Description: `Manages email template settings`,
Attributes: map[string]schema.Attribute{
"id": schema.StringAttribute{
Description: "The ID of the resource. This is a compound ID of the brand ID and the template name.",
Computed: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.UseStateForUnknown(),
},
},
"brand_id": schema.StringAttribute{
Description: "The ID of the brand.",
Required: true,
},
"template_name": schema.StringAttribute{
Description: "Email template name - Example values: `AccountLockout`,`ADForgotPassword`,`ADForgotPasswordDenied`,`ADSelfServiceUnlock`,`ADUserActivation`,`AuthenticatorEnrolled`,`AuthenticatorReset`,`ChangeEmailConfirmation`,`EmailChallenge`,`EmailChangeConfirmation`,`EmailFactorVerification`,`ForgotPassword`,`ForgotPasswordDenied`,`IGAReviewerEndNotification`,`IGAReviewerNotification`,`IGAReviewerPendingNotification`,`IGAReviewerReassigned`,`LDAPForgotPassword`,`LDAPForgotPasswordDenied`,`LDAPSelfServiceUnlock`,`LDAPUserActivation`,`MyAccountChangeConfirmation`,`NewSignOnNotification`,`OktaVerifyActivation`,`PasswordChanged`,`PasswordResetByAdmin`,`PendingEmailChange`,`RegistrationActivation`,`RegistrationEmailVerification`,`SelfServiceUnlock`,`SelfServiceUnlockOnUnlockedAccount`,`UserActivation`",
Required: true,
},
"recipients": schema.StringAttribute{
Description: "The recipients the emails of this template will be sent to - Valid values: `ALL_USERS`, `ADMINS_ONLY`, `NO_USERS`",
Required: true,
},
},
}
}

func (r *emailTemplateSettingsResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
r.Config = resourceConfiguration(req, resp)
}

// Unable to true create because there must always be a template setting
func (r *emailTemplateSettingsResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
var plan emailTemplateSettingsResourceModel

resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...)
if resp.Diagnostics.HasError() {
return
}

err := r.put(ctx, plan)
if err != nil {
resp.Diagnostics.AddError(
"failed to update email template settings",
err.Error(),
)
return
}
plan.ID = types.StringValue(formatId(plan.BrandID.ValueString(), plan.TemplateName.ValueString()))

resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...)
if resp.Diagnostics.HasError() {
return
}
}

func (r *emailTemplateSettingsResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
var state emailTemplateSettingsResourceModel
diags := req.State.Get(ctx, &state)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}

emailSettings, _, err := r.oktaSDKClientV3.CustomizationAPI.GetEmailSettings(ctx, state.BrandID.ValueString(), state.TemplateName.ValueString()).Execute()
if err != nil {
resp.Diagnostics.AddError(
"failed to read email template settings",
err.Error(),
)
return
}

state.Recipients = types.StringValue(emailSettings.Recipients)

diags = resp.State.Set(ctx, state)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
}

// Noop for delete because there must always be a template setting
func (r *emailTemplateSettingsResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
}

func (r *emailTemplateSettingsResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
var plan emailTemplateSettingsResourceModel

resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...)
if resp.Diagnostics.HasError() {
return
}

err := r.put(ctx, plan)
if err != nil {
resp.Diagnostics.AddError(
"failed to update email template settings",
err.Error(),
)
return
}
plan.ID = types.StringValue(formatId(plan.BrandID.ValueString(), plan.TemplateName.ValueString()))

resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...)
if resp.Diagnostics.HasError() {
return
}
}

func (r *emailTemplateSettingsResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp)
}

func (r *emailTemplateSettingsResource) put(ctx context.Context, plan emailTemplateSettingsResourceModel) error {
emailSettings := buildEmailSettings(plan)
_, err := r.oktaSDKClientV3.CustomizationAPI.ReplaceEmailSettings(ctx, plan.BrandID.ValueString(), plan.TemplateName.ValueString()).EmailSettings(emailSettings).Execute()
return err
}

func formatId(brandID string, templateName string) string {
return fmt.Sprintf("%s/%s", brandID, templateName)
}

func buildEmailSettings(model emailTemplateSettingsResourceModel) okta.EmailSettings {
emailSettings := okta.EmailSettings{}
emailSettings.SetRecipients(model.Recipients.ValueString())
return emailSettings
}
38 changes: 38 additions & 0 deletions okta/resource_okta_email_template_settings_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package okta

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
)

func TestAccResourceOktaEmailTemplateSettings(t *testing.T) {
_resource := "okta_email_template_settings"
resourceName := fmt.Sprintf("%s.test", _resource)
mgr := newFixtureManager("resources", _resource, t.Name())
config := mgr.GetFixtures("basic.tf", t)
updated := mgr.GetFixtures("updated.tf", t)
oktaResourceTest(t, resource.TestCase{
PreCheck: testAccPreCheck(t),
ErrorCheck: testAccErrorChecks(t),
ProtoV5ProviderFactories: testAccMergeProvidersFactories,
CheckDestroy: nil,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "recipients", "NO_USERS"),
resource.TestCheckResourceAttr(resourceName, "template_name", "UserActivation"),
),
},
{
Config: updated,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "recipients", "ADMINS_ONLY"),
resource.TestCheckResourceAttr(resourceName, "template_name", "UserActivation"),
),
},
},
})
}
Loading

0 comments on commit 48f3323

Please sign in to comment.