Skip to content

Commit

Permalink
Merge pull request #1842 from okta/OKTA-671022
Browse files Browse the repository at this point in the history
add datasource default signin page
  • Loading branch information
duytiennguyen-okta authored Dec 8, 2023
2 parents 14486f9 + 1f5d44d commit 151744a
Show file tree
Hide file tree
Showing 12 changed files with 971 additions and 1 deletion.
7 changes: 7 additions & 0 deletions examples/data-sources/okta_default_signin_page/datasource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
data "okta_brands" "test" {
}


data "okta_default_signin_page" "test" {
brand_id = tolist(data.okta_brands.test.brands)[0].id
}
14 changes: 14 additions & 0 deletions examples/resources/okta_customized_signin_page/basic.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
resource "okta_brand" "test" {
name = "testBrand"
locale = "en"
}

resource "okta_customized_signin_page" "test" {
brand_id = resource.okta_brand.test.id
page_content = "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n<html>\n<head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <meta name=\"robots\" content=\"noindex,nofollow\" />\n <!-- Styles generated from theme -->\n <link href=\"{{themedStylesUrl}}\" rel=\"stylesheet\" type=\"text/css\">\n <!-- Favicon from theme -->\n <link rel=\"shortcut icon\" href=\"{{faviconUrl}}\" type=\"image/x-icon\"/>\n\n <title>{{pageTitle}}</title>\n {{{SignInWidgetResources}}}\n\n <style nonce=\"{{nonceValue}}\">\n #login-bg-image-id {\n background-image: {{bgImageUrl}}\n }\n </style>\n</head>\n<body>\n <div id=\"login-bg-image-id\" class=\"login-bg-image tb--background\"></div>\n <div id=\"okta-login-container\"></div>\n\n <!--\n \"OktaUtil\" defines a global OktaUtil object\n that contains methods used to complete the Okta login flow.\n -->\n {{{OktaUtil}}}\n\n <script type=\"text/javascript\" nonce=\"{{nonceValue}}\">\n // \"config\" object contains default widget configuration\n // with any custom overrides defined in your admin settings.\n var config = OktaUtil.getSignInWidgetConfig();\n\n // Render the Okta Sign-In Widget\n var oktaSignIn = new OktaSignIn(config);\n oktaSignIn.renderEl({ el: '#okta-login-container' },\n OktaUtil.completeLogin,\n function(error) {\n // Logs errors that occur when configuring the widget.\n // Remove or replace this with your own custom error handler.\n console.log(error.message, error);\n }\n );\n </script>\n</body>\n</html>\n"
widget_version = "^6"
widget_customizations {
widget_generation = "G3"
}
}

14 changes: 14 additions & 0 deletions examples/resources/okta_preview_signin_page/basic.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
resource "okta_brand" "test" {
name = "testBrand"
locale = "en"
}

resource "okta_preview_signin_page" "test" {
brand_id = resource.okta_brand.test.id
page_content = "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n<html>\n<head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <meta name=\"robots\" content=\"noindex,nofollow\" />\n <!-- Styles generated from theme -->\n <link href=\"{{themedStylesUrl}}\" rel=\"stylesheet\" type=\"text/css\">\n <!-- Favicon from theme -->\n <link rel=\"shortcut icon\" href=\"{{faviconUrl}}\" type=\"image/x-icon\"/>\n\n <title>{{pageTitle}}</title>\n {{{SignInWidgetResources}}}\n\n <style nonce=\"{{nonceValue}}\">\n #login-bg-image-id {\n background-image: {{bgImageUrl}}\n }\n </style>\n</head>\n<body>\n <div id=\"login-bg-image-id\" class=\"login-bg-image tb--background\"></div>\n <div id=\"okta-login-container\"></div>\n\n <!--\n \"OktaUtil\" defines a global OktaUtil object\n that contains methods used to complete the Okta login flow.\n -->\n {{{OktaUtil}}}\n\n <script type=\"text/javascript\" nonce=\"{{nonceValue}}\">\n // \"config\" object contains default widget configuration\n // with any custom overrides defined in your admin settings.\n var config = OktaUtil.getSignInWidgetConfig();\n\n // Render the Okta Sign-In Widget\n var oktaSignIn = new OktaSignIn(config);\n oktaSignIn.renderEl({ el: '#okta-login-container' },\n OktaUtil.completeLogin,\n function(error) {\n // Logs errors that occur when configuring the widget.\n // Remove or replace this with your own custom error handler.\n console.log(error.message, error);\n }\n );\n </script>\n</body>\n</html>\n"
widget_version = "^6"
widget_customizations {
widget_generation = "G3"
}
}

437 changes: 437 additions & 0 deletions okta/customization.go

Large diffs are not rendered by default.

73 changes: 73 additions & 0 deletions okta/data_source_okta_default_signin_page.go
Original file line number Diff line number Diff line change
@@ -1 +1,74 @@
package okta

import (
"context"
"fmt"

"github.com/hashicorp/terraform-plugin-framework/datasource"
)

// Ensure the implementation satisfies the expected interfaces.
var (
_ datasource.DataSource = &defaultSigninPageDataSource{}
_ datasource.DataSourceWithConfigure = &defaultSigninPageDataSource{}
)

func NewDefaultSigninPageDataSource() datasource.DataSource {
return &defaultSigninPageDataSource{}
}

type defaultSigninPageDataSource struct {
*Config
}

func (d *defaultSigninPageDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_default_signin_page"
}

func (d *defaultSigninPageDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
newSchema := dataSourceSignInSchema
newSchema.Description = "Retrieve the default signin page of a brand"
resp.Schema = newSchema
}

func (d *defaultSigninPageDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
if req.ProviderData == nil {
return
}

config, ok := req.ProviderData.(*Config)
if !ok {
resp.Diagnostics.AddError(
"Unexpected Datasource Configure Type",
fmt.Sprintf("Expected *Config, got: %T. Please report this issue to the provider developers.", req.ProviderData),
)
return
}

d.Config = config
}

func (d *defaultSigninPageDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
var data signinPageModel

resp.Diagnostics.Append(resp.State.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}

defaultSigninPage, _, err := d.Config.oktaSDKClientV3.CustomizationAPI.GetDefaultSignInPage(ctx, data.BrandID.ValueString()).Execute()
if err != nil {
resp.Diagnostics.AddError(
"Error retrieving default signin page",
fmt.Sprintf("Error returned: %s", err.Error()),
)
return
}

resp.Diagnostics.Append(mapSignInPageToState(ctx, defaultSigninPage, &data)...)
if resp.Diagnostics.HasError() {
return
}

resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}
38 changes: 38 additions & 0 deletions okta/data_source_okta_default_signin_page_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 TestAccDataSourceOktaDefaultSigninPage_read(t *testing.T) {
mgr := newFixtureManager("data-sources", "okta_default_signin_page", t.Name())
resourceName := fmt.Sprintf("data.%s.test", "okta_default_signin_page")

oktaResourceTest(t, resource.TestCase{
PreCheck: testAccPreCheck(t),
ErrorCheck: testAccErrorChecks(t),
ProtoV5ProviderFactories: testAccMergeProvidersFactories,
Steps: []resource.TestStep{
{
Config: mgr.GetFixtures("datasource.tf", t),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttrSet(resourceName, "id"),
resource.TestCheckResourceAttr(resourceName, "widget_version", "^7"),
resource.TestCheckResourceAttr(resourceName, "widget_customizations.sign_in_label", "Sign In"),
resource.TestCheckResourceAttr(resourceName, "widget_customizations.username_label", "Username"),
resource.TestCheckResourceAttr(resourceName, "widget_customizations.password_label", "Password"),
resource.TestCheckResourceAttr(resourceName, "widget_customizations.show_password_visibility_toggle", "true"),
resource.TestCheckResourceAttr(resourceName, "widget_customizations.show_user_identifier", "true"),
resource.TestCheckResourceAttr(resourceName, "widget_customizations.forgot_password_label", "Forgot password?"),
resource.TestCheckResourceAttr(resourceName, "widget_customizations.unlock_account_label", "Unlock account?"),
resource.TestCheckResourceAttr(resourceName, "widget_customizations.help_label", "Help"),
resource.TestCheckResourceAttr(resourceName, "widget_customizations.classic_recovery_flow_email_or_username_label", "Email or Username"),
resource.TestCheckResourceAttr(resourceName, "widget_customizations.widget_generation", "G2"),
),
},
},
})
}
2 changes: 1 addition & 1 deletion okta/data_source_okta_org_metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ func (d *OrgMetadataDataSource) Configure(ctx context.Context, req datasource.Co
config, ok := req.ProviderData.(*Config)
if !ok {
resp.Diagnostics.AddError(
"Unexpected Resource Configure Type",
"Unexpected Datasource Configure Type",
fmt.Sprintf("Expected *Config, got: %T. Please report this issue to the provider developers.", req.ProviderData),
)
return
Expand Down
3 changes: 3 additions & 0 deletions okta/framework_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ func (p *FrameworkProvider) Configure(ctx context.Context, req provider.Configur
func (p *FrameworkProvider) DataSources(_ context.Context) []func() datasource.DataSource {
return []func() datasource.DataSource{
NewOrgMetadataDataSource,
NewDefaultSigninPageDataSource,
}
}

Expand All @@ -261,5 +262,7 @@ func (p *FrameworkProvider) Resources(_ context.Context) []func() resource.Resou
NewPolicyDeviceAssuranceIOSResource,
NewPolicyDeviceAssuranceMacOSResource,
NewPolicyDeviceAssuranceWindowsResource,
NewCustomizedSigninResource,
NewPreviewSigninResource,
}
}
165 changes: 165 additions & 0 deletions okta/resource_okta_customized_signin_page.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
package okta

import (
"context"
"fmt"

"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/resource"
)

// Ensure the implementation satisfies the expected interfaces.
var (
_ resource.Resource = &customizedSigninPageResource{}
_ resource.ResourceWithConfigure = &customizedSigninPageResource{}
_ resource.ResourceWithImportState = &customizedSigninPageResource{}
)

func NewCustomizedSigninResource() resource.Resource {
return &customizedSigninPageResource{}
}

type customizedSigninPageResource struct {
*Config
}

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

func (r *customizedSigninPageResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
newSchema := resourceSignInSchema
newSchema.Description = "Manage the customized signin page of a brand"
resp.Schema = newSchema
}

// Configure adds the provider configured client to the resource.
func (r *customizedSigninPageResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
if req.ProviderData == nil {
return
}

p, ok := req.ProviderData.(*Config)
if !ok {
resp.Diagnostics.AddError(
"Unexpected Resource Configure Type",
fmt.Sprintf("Expected *Config, got: %T. Please report this issue to the provider developers.", req.ProviderData),
)
return
}

r.Config = p
}

func (r *customizedSigninPageResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
var state signinPageModel
resp.Diagnostics.Append(req.Plan.Get(ctx, &state)...)
if resp.Diagnostics.HasError() {
return
}

reqBody, err := buildSignInPageRequest(ctx, state)
if err != nil {
resp.Diagnostics.AddError(
"failed to build customized sign in page",
err.Error(),
)
return
}

customizedSigninPage, _, err := r.oktaSDKClientV3.CustomizationAPI.ReplaceCustomizedSignInPage(ctx, state.BrandID.ValueString()).SignInPage(reqBody).Execute()
if err != nil {
resp.Diagnostics.AddError(
"failed to update customized sign in page",
err.Error(),
)
return
}

resp.Diagnostics.Append(mapSignInPageToState(ctx, customizedSigninPage, &state)...)
if resp.Diagnostics.HasError() {
return
}

resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
}

func (r *customizedSigninPageResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
var state signinPageModel

resp.Diagnostics.Append(resp.State.Get(ctx, &state)...)
if resp.Diagnostics.HasError() {
return
}

customizedSigninPage, _, err := r.Config.oktaSDKClientV3.CustomizationAPI.GetCustomizedSignInPage(ctx, state.BrandID.ValueString()).Execute()
if err != nil {
resp.Diagnostics.AddError(
"Error retrieving customized signin page",
fmt.Sprintf("Error returned: %s", err.Error()),
)
return
}

resp.Diagnostics.Append(mapSignInPageToState(ctx, customizedSigninPage, &state)...)
if resp.Diagnostics.HasError() {
return
}

// Save data into state
resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
}

func (r *customizedSigninPageResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
var state signinPageModel
resp.Diagnostics.Append(req.State.Get(ctx, &state)...)
if resp.Diagnostics.HasError() {
return
}

_, err := r.oktaSDKClientV3.CustomizationAPI.DeleteCustomizedSignInPage(ctx, state.ID.ValueString()).Execute()
if err != nil {
resp.Diagnostics.AddError(
"failed to delete customized signin page",
err.Error(),
)
return
}
}

func (r *customizedSigninPageResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
var state signinPageModel
resp.Diagnostics.Append(req.Plan.Get(ctx, &state)...)
if resp.Diagnostics.HasError() {
return
}

reqBody, err := buildSignInPageRequest(ctx, state)
if err != nil {
resp.Diagnostics.AddError(
"failed to build customized sign in page",
err.Error(),
)
return
}

customizedSigninPage, _, err := r.oktaSDKClientV3.CustomizationAPI.ReplaceCustomizedSignInPage(ctx, state.BrandID.ValueString()).SignInPage(reqBody).Execute()
if err != nil {
resp.Diagnostics.AddError(
"failed to update customized sign in page",
err.Error(),
)
return
}

resp.Diagnostics.Append(mapSignInPageToState(ctx, customizedSigninPage, &state)...)
if resp.Diagnostics.HasError() {
return
}

resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
}

func (r *customizedSigninPageResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp)
}
27 changes: 27 additions & 0 deletions okta/resource_okta_customized_signin_page_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package okta

import (
"testing"

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

func TestAccResourceOktaCustomizedSignInPage_crud(t *testing.T) {
mgr := newFixtureManager("resources", "okta_customized_signin_page", t.Name())

oktaResourceTest(t, resource.TestCase{
PreCheck: testAccPreCheck(t),
ErrorCheck: testAccErrorChecks(t),
ProtoV5ProviderFactories: testAccMergeProvidersFactories,
Steps: []resource.TestStep{
{
Config: mgr.GetFixtures("basic.tf", t),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("okta_customized_signin_page.test", "page_content", "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n<html>\n<head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <meta name=\"robots\" content=\"noindex,nofollow\" />\n <!-- Styles generated from theme -->\n <link href=\"{{themedStylesUrl}}\" rel=\"stylesheet\" type=\"text/css\">\n <!-- Favicon from theme -->\n <link rel=\"shortcut icon\" href=\"{{faviconUrl}}\" type=\"image/x-icon\"/>\n\n <title>{{pageTitle}}</title>\n {{{SignInWidgetResources}}}\n\n <style nonce=\"{{nonceValue}}\">\n #login-bg-image-id {\n background-image: {{bgImageUrl}}\n }\n </style>\n</head>\n<body>\n <div id=\"login-bg-image-id\" class=\"login-bg-image tb--background\"></div>\n <div id=\"okta-login-container\"></div>\n\n <!--\n \"OktaUtil\" defines a global OktaUtil object\n that contains methods used to complete the Okta login flow.\n -->\n {{{OktaUtil}}}\n\n <script type=\"text/javascript\" nonce=\"{{nonceValue}}\">\n // \"config\" object contains default widget configuration\n // with any custom overrides defined in your admin settings.\n var config = OktaUtil.getSignInWidgetConfig();\n\n // Render the Okta Sign-In Widget\n var oktaSignIn = new OktaSignIn(config);\n oktaSignIn.renderEl({ el: '#okta-login-container' },\n OktaUtil.completeLogin,\n function(error) {\n // Logs errors that occur when configuring the widget.\n // Remove or replace this with your own custom error handler.\n console.log(error.message, error);\n }\n );\n </script>\n</body>\n</html>\n"),
resource.TestCheckResourceAttr("okta_customized_signin_page.test", "widget_version", "^6"),
resource.TestCheckResourceAttr("okta_customized_signin_page.test", "widget_customizations.widget_generation", "G3"),
),
},
},
})
}
Loading

0 comments on commit 151744a

Please sign in to comment.