Files
hanko/backend/flow_api/flow/user_details/action_set_email.go
bjoern-m 601ffaae92 Introduce Flowpilot - integration (#1532)
This pull request introduces the new Flowpilot system along with several new features and various improvements. The key enhancements include configurable authorization, registration, and profile flows, as well as the ability to enable and disable user identifiers (e.g., email addresses and usernames) and login methods.

---------

Co-authored-by: Frederic Jahn <frederic.jahn@hanko.io>
Co-authored-by: Lennart Fleischmann <lennart.fleischmann@hanko.io>
Co-authored-by: lfleischmann <67686424+lfleischmann@users.noreply.github.com>
Co-authored-by: merlindru <hello@merlindru.com>
2024-08-06 16:07:29 +02:00

88 lines
2.5 KiB
Go

package user_details
import (
"fmt"
"github.com/teamhanko/hanko/backend/flow_api/flow/shared"
"github.com/teamhanko/hanko/backend/flowpilot"
)
type EmailAddressSet struct {
shared.Action
}
func (a EmailAddressSet) GetName() flowpilot.ActionName {
return shared.ActionEmailAddressSet
}
func (a EmailAddressSet) GetDescription() string {
return "Set a new email address."
}
func (a EmailAddressSet) Initialize(c flowpilot.InitializationContext) {
deps := a.GetDeps(c)
c.AddInputs(flowpilot.StringInput("email").
Required(!deps.Cfg.Email.Optional).
MaxLength(deps.Cfg.Email.MaxLength).
Preserve(true).
TrimSpace(true).
LowerCase(true))
}
func (a EmailAddressSet) Execute(c flowpilot.ExecutionContext) error {
deps := a.GetDeps(c)
if valid := c.ValidateInputData(); !valid {
return c.Error(flowpilot.ErrorFormDataInvalid)
}
email := c.Input().Get("email").String()
err := c.Stash().Set(shared.StashPathEmail, email)
if err != nil {
return fmt.Errorf("failed to stash email address: %w", err)
}
existingEmail, err := deps.Persister.GetEmailPersister().FindByAddress(email)
if err != nil {
return fmt.Errorf("failed to get email from db: %w", err)
}
if deps.Cfg.Email.RequireVerification {
// Email verification is enabled. Send an email regardless of whether the email address exists, but select the
// appropriate passcode template beforehand.
if existingEmail != nil {
err = c.Stash().Set(shared.StashPathPasscodeTemplate, "email_registration_attempted") // "email_verification"
if err != nil {
return fmt.Errorf("failed to set passcode_template to the stash: %w", err)
}
} else {
err = c.Stash().Set(shared.StashPathPasscodeTemplate, "email_verification")
if err != nil {
return fmt.Errorf("failed to set passcode_template to the stash: %w", err)
}
}
if err = c.Stash().Set(shared.StashPathLoginOnboardingCreateEmail, true); err != nil {
return fmt.Errorf("failed to set login_onboarding_create_email to the stash: %w", err)
}
return c.Continue(shared.StatePasscodeConfirmation)
}
// Email verification is turned off, hence we can display an error if the email already exists, or continue the flow
// without passcode verification otherwise.
if existingEmail != nil {
c.Input().SetError("email", shared.ErrorEmailAlreadyExists)
return c.Error(flowpilot.ErrorFormDataInvalid)
}
if err = c.Stash().Set(shared.StashPathLoginOnboardingCreateEmail, true); err != nil {
return fmt.Errorf("failed to set login_onboarding_create_email to the stash: %w", err)
}
c.PreventRevert()
return c.Continue()
}