2525type GenerateLinkParams struct {
2626 Type string `json:"type"`
2727 Email string `json:"email"`
28+ NewEmail string `json:"new_email"`
2829 Password string `json:"password"`
2930 Data map [string ]interface {} `json:"data"`
3031 RedirectTo string `json:"redirect_to"`
@@ -52,13 +53,13 @@ func (a *API) GenerateLink(w http.ResponseWriter, r *http.Request) error {
5253 user , err := models .FindUserByEmailAndAudience (a .db , instanceID , params .Email , aud )
5354 if err != nil {
5455 if models .IsNotFoundError (err ) {
55- if params .Type == "magiclink" {
56- params .Type = "signup"
56+ if params .Type == magicLinkVerification {
57+ params .Type = signupVerification
5758 params .Password , err = password .Generate (64 , 10 , 0 , false , true )
5859 if err != nil {
5960 return internalServerError ("error creating user" ).WithInternalError (err )
6061 }
61- } else if params .Type == "recovery " {
62+ } else if params .Type == recoveryVerification || params . Type == "email_change_current" || params . Type == "email_change_new " {
6263 return notFoundError (err .Error ())
6364 }
6465 } else {
@@ -77,14 +78,14 @@ func (a *API) GenerateLink(w http.ResponseWriter, r *http.Request) error {
7778 err = a .db .Transaction (func (tx * storage.Connection ) error {
7879 var terr error
7980 switch params .Type {
80- case "magiclink" , "recovery" :
81+ case magicLinkVerification , recoveryVerification :
8182 if terr = models .NewAuditLogEntry (tx , instanceID , user , models .UserRecoveryRequestedAction , "" , nil ); terr != nil {
8283 return terr
8384 }
8485 user .RecoveryToken = hashedToken
8586 user .RecoverySentAt = & now
8687 terr = errors .Wrap (tx .UpdateOnly (user , "recovery_token" , "recovery_sent_at" ), "Database error updating user for recovery" )
87- case "invite" :
88+ case inviteVerification :
8889 if user != nil {
8990 if user .IsConfirmed () {
9091 return unprocessableEntityError (DuplicateEmailMsg )
@@ -111,7 +112,7 @@ func (a *API) GenerateLink(w http.ResponseWriter, r *http.Request) error {
111112 user .ConfirmationSentAt = & now
112113 user .InvitedAt = & now
113114 terr = errors .Wrap (tx .UpdateOnly (user , "confirmation_token" , "confirmation_sent_at" , "invited_at" ), "Database error updating user for invite" )
114- case "signup" :
115+ case signupVerification :
115116 if user != nil {
116117 if user .IsConfirmed () {
117118 return unprocessableEntityError (DuplicateEmailMsg )
@@ -141,6 +142,28 @@ func (a *API) GenerateLink(w http.ResponseWriter, r *http.Request) error {
141142 user .ConfirmationToken = hashedToken
142143 user .ConfirmationSentAt = & now
143144 terr = errors .Wrap (tx .UpdateOnly (user , "confirmation_token" , "confirmation_sent_at" ), "Database error updating user for confirmation" )
145+ case "email_change_current" , "email_change_new" :
146+ if ! config .Mailer .SecureEmailChangeEnabled && params .Type == "email_change_current" {
147+ return unprocessableEntityError ("Enable secure email change to generate link for current email" )
148+ }
149+ if terr := a .validateEmail (ctx , params .NewEmail ); terr != nil {
150+ return unprocessableEntityError ("The new email address provided is invalid" )
151+ }
152+ if exists , terr := models .IsDuplicatedEmail (tx , instanceID , params .NewEmail , user .Aud ); terr != nil {
153+ return internalServerError ("Database error checking email" ).WithInternalError (terr )
154+ } else if exists {
155+ return unprocessableEntityError (DuplicateEmailMsg )
156+ }
157+ now := time .Now ()
158+ user .EmailChangeSentAt = & now
159+ user .EmailChange = params .NewEmail
160+ user .EmailChangeConfirmStatus = zeroConfirmation
161+ if params .Type == "email_change_current" {
162+ user .EmailChangeTokenCurrent = hashedToken
163+ } else if params .Type == "email_change_new" {
164+ user .EmailChangeTokenNew = fmt .Sprintf ("%x" , sha256 .Sum224 ([]byte (params .NewEmail + otp )))
165+ }
166+ terr = errors .Wrap (tx .UpdateOnly (user , "email_change_token_current" , "email_change_token_new" , "email_change" , "email_change_sent_at" , "email_change_confirm_status" ), "Database error updating user for email change" )
144167 default :
145168 return badRequestError ("Invalid email action link type requested: %v" , params .Type )
146169 }
0 commit comments