mirror of
https://github.com/zitadel/zitadel.git
synced 2024-12-16 21:08:00 +00:00
f653589609
# Which Problems Are Solved The recently added possibility to generate and verify codes through Twilio verification service did failed on checking OTP SMS code through the session API. Additionally, password codes generated by the V2 API and sent through phone would always use the internal generator and verification mechanism rather than the configured. # How the Problems Are Solved - Correctly set the verifier for OTP SMS for the session API - Always use the internal verifier for OTP Email (for now) - Select the generator / verifier based on the configuration for password codes with notification type SMS for V2 APIs # Additional Changes None # Additional Context - relates to #8678 - reported by customer --------- Co-authored-by: Stefan Benz <46600784+stebenz@users.noreply.github.com>
78 lines
3.6 KiB
Go
78 lines
3.6 KiB
Go
package command
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
|
|
"github.com/zitadel/zitadel/internal/api/authz"
|
|
"github.com/zitadel/zitadel/internal/domain"
|
|
"github.com/zitadel/zitadel/internal/repository/user"
|
|
"github.com/zitadel/zitadel/internal/zerrors"
|
|
)
|
|
|
|
// RequestPasswordReset generates a code
|
|
// and triggers a notification e-mail with the default confirmation URL format.
|
|
func (c *Commands) RequestPasswordReset(ctx context.Context, userID string) (*domain.ObjectDetails, *string, error) {
|
|
return c.requestPasswordReset(ctx, userID, false, "", domain.NotificationTypeEmail)
|
|
}
|
|
|
|
// RequestPasswordResetURLTemplate generates a code
|
|
// and triggers a notification e-mail with the confirmation URL rendered from the passed urlTmpl.
|
|
// urlTmpl must be a valid [tmpl.Template].
|
|
func (c *Commands) RequestPasswordResetURLTemplate(ctx context.Context, userID, urlTmpl string, notificationType domain.NotificationType) (*domain.ObjectDetails, *string, error) {
|
|
if err := domain.RenderConfirmURLTemplate(io.Discard, urlTmpl, userID, "code", "orgID"); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
return c.requestPasswordReset(ctx, userID, false, urlTmpl, notificationType)
|
|
}
|
|
|
|
// RequestPasswordResetReturnCode generates a code and does not send a notification email.
|
|
// The generated plain text code will be returned.
|
|
func (c *Commands) RequestPasswordResetReturnCode(ctx context.Context, userID string) (*domain.ObjectDetails, *string, error) {
|
|
return c.requestPasswordReset(ctx, userID, true, "", 0)
|
|
}
|
|
|
|
// requestPasswordReset creates a code for a password change.
|
|
// returnCode controls if the plain text version of the code will be set in the return object.
|
|
// When the plain text code is returned, no notification e-mail will be sent to the user.
|
|
// urlTmpl allows changing the target URL that is used by the e-mail and should be a validated Go template, if used.
|
|
func (c *Commands) requestPasswordReset(ctx context.Context, userID string, returnCode bool, urlTmpl string, notificationType domain.NotificationType) (_ *domain.ObjectDetails, plainCode *string, err error) {
|
|
if userID == "" {
|
|
return nil, nil, zerrors.ThrowInvalidArgument(nil, "COMMAND-SAFdda", "Errors.User.IDMissing")
|
|
}
|
|
model, err := c.getHumanWriteModelByID(ctx, userID, "")
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
if !model.UserState.Exists() {
|
|
return nil, nil, zerrors.ThrowNotFound(nil, "COMMAND-SAF4f", "Errors.User.NotFound")
|
|
}
|
|
if model.UserState == domain.UserStateInitial {
|
|
return nil, nil, zerrors.ThrowPreconditionFailed(nil, "COMMAND-Sfe4g", "Errors.User.NotInitialised")
|
|
}
|
|
if authz.GetCtxData(ctx).UserID != userID {
|
|
if err = c.checkPermission(ctx, domain.PermissionUserWrite, model.ResourceOwner, userID); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
}
|
|
var passwordCode *EncryptedCode
|
|
var generatorID string
|
|
if notificationType == domain.NotificationTypeSms {
|
|
passwordCode, generatorID, err = c.newPhoneCode(ctx, c.eventstore.Filter, domain.SecretGeneratorTypePasswordResetCode, c.userEncryption, c.defaultSecretGenerators.PasswordVerificationCode) //nolint:staticcheck
|
|
} else {
|
|
passwordCode, err = c.newEncryptedCode(ctx, c.eventstore.Filter, domain.SecretGeneratorTypePasswordResetCode, c.userEncryption) //nolint:staticcheck
|
|
}
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
cmd := user.NewHumanPasswordCodeAddedEventV2(ctx, UserAggregateFromWriteModelCtx(ctx, &model.WriteModel), passwordCode.CryptedCode(), passwordCode.CodeExpiry(), notificationType, urlTmpl, returnCode, generatorID)
|
|
|
|
if returnCode {
|
|
plainCode = &passwordCode.Plain
|
|
}
|
|
if err = c.pushAppendAndReduce(ctx, model, cmd); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
return writeModelToObjectDetails(&model.WriteModel), plainCode, nil
|
|
}
|