Skip to content

Commit

Permalink
Add support for new Prompts and Screens for Prompt Partial (#437)
Browse files Browse the repository at this point in the history
  • Loading branch information
developerkunal authored Sep 2, 2024
1 parent 0c331b7 commit e31d23f
Show file tree
Hide file tree
Showing 8 changed files with 742 additions and 1 deletion.
13 changes: 13 additions & 0 deletions management/management.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions management/management.gen_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

105 changes: 104 additions & 1 deletion management/prompt.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ const (

// PromptLoginPassword represents the login-password prompt.
PromptLoginPassword PromptType = "login-password"

// PromptLoginPasswordLess represents the login-passwordless prompt.
PromptLoginPasswordLess PromptType = "login-passwordless"
)

var allowedPromptsWithPartials = []PromptType{
Expand All @@ -33,11 +36,73 @@ var allowedPromptsWithPartials = []PromptType{
PromptLogin,
PromptLoginID,
PromptLoginPassword,
PromptLoginPasswordLess,
}

// PromptType defines the prompt that we are managing.
type PromptType string

// ScreenName is a type that represents the name of a screen.
type ScreenName string

// InsertionPoint is a type that represents the insertion point of a screen.
type InsertionPoint string

const (
// ScreenLogin represents the login screen.
ScreenLogin ScreenName = "login"

// ScreenLoginID represents the login-id screen.
ScreenLoginID ScreenName = "login-id"

// ScreenLoginPassword represents the login-password screen.
ScreenLoginPassword ScreenName = "login-password"

// ScreenSignup represents the signup screen.
ScreenSignup ScreenName = "signup"

// ScreenSignupID represents the signup-id screen.
ScreenSignupID ScreenName = "signup-id"

// ScreenSignupPassword represents the signup-password screen.
ScreenSignupPassword ScreenName = "signup-password"

// ScreenLoginPasswordlessSMSOTP represents the login-passwordless-sms-otp screen.
ScreenLoginPasswordlessSMSOTP ScreenName = "login-passwordless-sms-otp"

// ScreenLoginPasswordlessEmailCode represents the login-passwordless-email-code screen.
ScreenLoginPasswordlessEmailCode ScreenName = "login-passwordless-email-code"
)

const (
// InsertionPointFormContentStart represents the form-content-start insertion point.
InsertionPointFormContentStart InsertionPoint = "form-content-start"

// InsertionPointFormContentEnd represents the form-content-end insertion point.
InsertionPointFormContentEnd InsertionPoint = "form-content-end"

// InsertionPointFormFooterStart represents the form-footer-start insertion point.
InsertionPointFormFooterStart InsertionPoint = "form-footer-start"

// InsertionPointFormFooterEnd represents the form-footer-end insertion point.
InsertionPointFormFooterEnd InsertionPoint = "form-footer-end"

// InsertionPointSecondaryActionsStart represents the secondary-actions-start insertion point.
InsertionPointSecondaryActionsStart InsertionPoint = "secondary-actions-start"

// InsertionPointSecondaryActionsEnd represents the secondary-actions-end insertion point.
InsertionPointSecondaryActionsEnd InsertionPoint = "secondary-actions-end"
)

// ScreenPartials is a map of insertion points to partials.
type ScreenPartials struct {
// Define InsertionPoints for the screen partials here
Content map[InsertionPoint]string
}

// PromptScreenPartials is a map of screen names to insertion points.
type PromptScreenPartials map[ScreenName]map[InsertionPoint]string

// Prompt is used within the Login Page.
//
// See: https://auth0.com/docs/customize/universal-login-pages/customize-login-text-prompts
Expand All @@ -54,6 +119,8 @@ type Prompt struct {

// PromptPartials to be used for Custom Prompt Partials.
//
// Deprecated: Use [PromptScreenPartials] instead.
//
// See: https://auth0.com/docs/sign-up-prompt-customizations
type PromptPartials struct {
FormContentStart string `json:"form-content-start,omitempty"`
Expand Down Expand Up @@ -127,6 +194,10 @@ func (m *PromptManager) SetCustomText(ctx context.Context, p string, l string, b

// CreatePartials creates new custom prompt partials for a given segment.
//
// Deprecated: Use [ SetPartials ] instead. The [ SetPartials ] method is preferred for setting prompt partials and provides a more consistent API.
//
// To create a partial with a different screen name and prompt name, use the [ SetPartials ] method with the [PromptScreenPartials] struct.
//
// See: https://auth0.com/docs/sign-up-prompt-customizations#use-the-api-to-edit-custom-prompts
func (m *PromptManager) CreatePartials(ctx context.Context, c *PromptPartials, opts ...RequestOption) error {
if err := guardAgainstPromptTypesWithNoPartials(c.Prompt); err != nil {
Expand All @@ -138,6 +209,10 @@ func (m *PromptManager) CreatePartials(ctx context.Context, c *PromptPartials, o

// UpdatePartials updates custom prompt partials for a given segment.
//
// Deprecated: Use [ SetPartials ] instead. The [ SetPartials ] method offers more flexibility and is the recommended approach for updating prompt partials.
//
// To update a partial with a different screen name and prompt name, use the [ SetPartials ] method with the [PromptScreenPartials] struct.
//
// See: https://auth0.com/docs/sign-up-prompt-customizations#use-the-api-to-edit-custom-prompts
func (m *PromptManager) UpdatePartials(ctx context.Context, c *PromptPartials, opts ...RequestOption) error {
if err := guardAgainstPromptTypesWithNoPartials(c.Prompt); err != nil {
Expand All @@ -147,8 +222,36 @@ func (m *PromptManager) UpdatePartials(ctx context.Context, c *PromptPartials, o
return m.management.Request(ctx, "PUT", m.management.URI("prompts", string(c.Prompt), "partials"), c, opts...)
}

// GetPartials retrieves custom prompt partials for a given segment.
//
// See : https://auth0.com/docs/api/management/v2/prompts/get-partials
func (m *PromptManager) GetPartials(ctx context.Context, prompt PromptType, opts ...RequestOption) (c *PromptScreenPartials, err error) {
if err := guardAgainstPromptTypesWithNoPartials(prompt); err != nil {
return nil, err
}

err = m.management.Request(ctx, "GET", m.management.URI("prompts", string(prompt), "partials"), &c, opts...)

return
}

// SetPartials sets custom prompt partials for a given segment.
//
// See : https://auth0.com/docs/api/management/v2/prompts/put-partials
func (m *PromptManager) SetPartials(ctx context.Context, prompt PromptType, c *PromptScreenPartials, opts ...RequestOption) error {
if err := guardAgainstPromptTypesWithNoPartials(prompt); err != nil {
return err
}

return m.management.Request(ctx, "PUT", m.management.URI("prompts", string(prompt), "partials"), &c, opts...)
}

// ReadPartials reads custom prompt partials for a given segment.
//
// Deprecated: Use [ GetPartials ] instead. The [ GetPartials ] method provides the same functionality with improved support and additional features.
//
// If there are multiple screen partials for a prompt, this method will return only the first screen partial. To retrieve all screen partials for a prompt, use the [ GetPartials ] method.
//
// See: https://auth0.com/docs/sign-up-prompt-customizations#use-the-api-to-edit-custom-prompts
func (m *PromptManager) ReadPartials(ctx context.Context, prompt PromptType, opts ...RequestOption) (c *PromptPartials, err error) {
if err := guardAgainstPromptTypesWithNoPartials(prompt); err != nil {
Expand All @@ -174,7 +277,7 @@ func (m *PromptManager) DeletePartials(ctx context.Context, prompt PromptType, o
return err
}

return m.management.Request(ctx, "PUT", m.management.URI("prompts", string(prompt), "partials"), &PromptPartials{Prompt: prompt}, opts...)
return m.management.Request(ctx, "PUT", m.management.URI("prompts", string(prompt), "partials"), &PromptScreenPartials{}, opts...)
}

func guardAgainstPromptTypesWithNoPartials(prompt PromptType) error {
Expand Down
97 changes: 97 additions & 0 deletions management/prompt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,76 @@ func TestPromptCustomText(t *testing.T) {
assert.Equal(t, "Welcome", texts["login"].(map[string]interface{})["title"])
}

func TestPromptManager_GetPartials(t *testing.T) {
configureHTTPTestRecordings(t)

_ = givenACustomDomain(t)
_ = givenAUniversalLoginTemplate(t)

prompt := PromptLogin

expected := givenAPartialPrompt(t, prompt)

actual, err := api.Prompt.GetPartials(context.Background(), prompt)

assert.NoError(t, err)
assert.Equal(t, expected, actual)
}

func TestPromptManager_SetPartials(t *testing.T) {
configureHTTPTestRecordings(t)

_ = givenACustomDomain(t)
_ = givenAUniversalLoginTemplate(t)

prompt := PromptLoginPasswordLess

expected := &PromptScreenPartials{
ScreenLoginPasswordlessSMSOTP: {
InsertionPointFormContentStart: `<div>Form Content Start</div>`,
InsertionPointFormContentEnd: `<div>Form Content Start</div>`,
},
ScreenLoginPasswordlessEmailCode: {
InsertionPointFormContentStart: `<div>Form Content Start</div>`,
InsertionPointFormContentEnd: `<div>Form Content Start</div>`,
},
}

err := api.Prompt.SetPartials(context.Background(), prompt, expected)
assert.NoError(t, err)

t.Cleanup(func() {
cleanupPromptPartials(t, prompt)
})

actual, err := api.Prompt.GetPartials(context.Background(), prompt)

assert.NoError(t, err)
assert.Equal(t, expected, actual)
}

func TestPromptManager_GetPartialsGuardGuardError(t *testing.T) {
configureHTTPTestRecordings(t)

prompt := PromptType("OtherPrompt")

_, err := api.Prompt.GetPartials(context.Background(), prompt)
assert.Error(t, err)
assert.ErrorContains(t, err, "cannot customize partials for prompt")
}

func TestPromptManager_SetPartialsGuardGuardError(t *testing.T) {
configureHTTPTestRecordings(t)

prompt := PromptType("OtherPrompt")

expected := &PromptScreenPartials{}

err := api.Prompt.SetPartials(context.Background(), prompt, expected)
assert.Error(t, err)
assert.ErrorContains(t, err, "cannot customize partials for prompt")
}

func TestPromptManager_ReadPartials(t *testing.T) {
configureHTTPTestRecordings(t)

Expand Down Expand Up @@ -202,3 +272,30 @@ func deleteUniversalLoginTemplate(t *testing.T) {
err := api.Branding.DeleteUniversalLogin(context.Background())
assert.NoError(t, err)
}

func givenAPartialPrompt(t *testing.T, prompt PromptType) *PromptScreenPartials {
t.Helper()

partials := &PromptScreenPartials{
ScreenLogin: {
InsertionPointFormContentStart: `<div>Form Content Start</div>`,
InsertionPointFormContentEnd: `<div>Form Content Start</div>`,
},
}

err := api.Prompt.SetPartials(context.Background(), prompt, partials)
assert.NoError(t, err)

t.Cleanup(func() {
cleanupPromptPartials(t, prompt)
})

return partials
}

func cleanupPromptPartials(t *testing.T, prompt PromptType) {
t.Helper()

err := api.Prompt.DeletePartials(context.Background(), prompt)
assert.NoError(t, err)
}
Loading

0 comments on commit e31d23f

Please sign in to comment.