fix: make user creation errors helpful (#5382)

* fix: make user creation errors helpful

* fix linting and unit testing errors

* fix linting

* make zitadel config reusable

* fix human validations

* translate ssr errors

* make zitadel config reusable

* cover more translations for ssr

* handle email validation message centrally

* fix unit tests

* fix linting

* align signatures

* use more precise wording

* handle phone validation message centrally

* fix: return specific profile errors

* docs: edit comments

* fix unit tests

---------

Co-authored-by: Silvan <silvan.reusser@gmail.com>
This commit is contained in:
Elio Bischof
2023-03-14 20:20:38 +01:00
committed by GitHub
parent 9ff810eb92
commit e00cc187fa
79 changed files with 610 additions and 485 deletions

View File

@@ -55,13 +55,13 @@ func (l *Login) runPostExternalAuthenticationActions(
actions.SetFields("setPreferredUsername", func(username string) {
user.PreferredUsername = username
}),
actions.SetFields("setEmail", func(email string) {
actions.SetFields("setEmail", func(email domain.EmailAddress) {
user.Email = email
}),
actions.SetFields("setEmailVerified", func(verified bool) {
user.IsEmailVerified = verified
}),
actions.SetFields("setPhone", func(phone string) {
actions.SetFields("setPhone", func(phone domain.PhoneNumber) {
user.Phone = phone
}),
actions.SetFields("setPhoneVerified", func(verified bool) {
@@ -222,7 +222,7 @@ func (l *Login) runPreCreationActions(
actions.SetFields("setUsername", func(username string) {
user.Username = username
}),
actions.SetFields("setEmail", func(email string) {
actions.SetFields("setEmail", func(email domain.EmailAddress) {
if user.Email == nil {
user.Email = &domain.Email{}
}
@@ -234,11 +234,11 @@ func (l *Login) runPreCreationActions(
}
user.Email.IsEmailVerified = verified
}),
actions.SetFields("setPhone", func(email string) {
actions.SetFields("setPhone", func(phone domain.PhoneNumber) {
if user.Phone == nil {
user.Phone = &domain.Phone{}
}
user.Phone.PhoneNumber = email
user.Phone.PhoneNumber = phone
}),
actions.SetFields("setPhoneVerified", func(verified bool) {
if user.Phone == nil {

View File

@@ -60,28 +60,28 @@ type externalNotFoundOptionData struct {
ShowUsername bool
ShowUsernameSuffix bool
OrgRegister bool
ExternalEmail string
ExternalEmail domain.EmailAddress
ExternalEmailVerified bool
ExternalPhone string
ExternalPhone domain.PhoneNumber
ExternalPhoneVerified bool
}
type externalRegisterFormData struct {
ExternalIDPConfigID string `schema:"external-idp-config-id"`
ExternalIDPExtUserID string `schema:"external-idp-ext-user-id"`
ExternalIDPDisplayName string `schema:"external-idp-display-name"`
ExternalEmail string `schema:"external-email"`
ExternalEmailVerified bool `schema:"external-email-verified"`
Email string `schema:"email"`
Username string `schema:"username"`
Firstname string `schema:"firstname"`
Lastname string `schema:"lastname"`
Nickname string `schema:"nickname"`
ExternalPhone string `schema:"external-phone"`
ExternalPhoneVerified bool `schema:"external-phone-verified"`
Phone string `schema:"phone"`
Language string `schema:"language"`
TermsConfirm bool `schema:"terms-confirm"`
ExternalIDPConfigID string `schema:"external-idp-config-id"`
ExternalIDPExtUserID string `schema:"external-idp-ext-user-id"`
ExternalIDPDisplayName string `schema:"external-idp-display-name"`
ExternalEmail domain.EmailAddress `schema:"external-email"`
ExternalEmailVerified bool `schema:"external-email-verified"`
Email domain.EmailAddress `schema:"email"`
Username string `schema:"username"`
Firstname string `schema:"firstname"`
Lastname string `schema:"lastname"`
Nickname string `schema:"nickname"`
ExternalPhone domain.PhoneNumber `schema:"external-phone"`
ExternalPhoneVerified bool `schema:"external-phone-verified"`
Phone domain.PhoneNumber `schema:"phone"`
Language string `schema:"language"`
TermsConfirm bool `schema:"terms-confirm"`
}
// handleExternalLoginStep is called as nextStep
@@ -815,7 +815,7 @@ func mapExternalNotFoundOptionFormDataToLoginUser(formData *externalNotFoundOpti
IDPConfigID: formData.ExternalIDPConfigID,
ExternalUserID: formData.ExternalIDPExtUserID,
PreferredUsername: formData.Username,
DisplayName: formData.Email,
DisplayName: string(formData.Email),
FirstName: formData.Firstname,
LastName: formData.Lastname,
NickName: formData.Nickname,

View File

@@ -16,14 +16,14 @@ const (
)
type registerFormData struct {
Email string `schema:"email"`
Username string `schema:"username"`
Firstname string `schema:"firstname"`
Lastname string `schema:"lastname"`
Language string `schema:"language"`
Password string `schema:"register-password"`
Password2 string `schema:"register-password-confirmation"`
TermsConfirm bool `schema:"terms-confirm"`
Email domain.EmailAddress `schema:"email"`
Username string `schema:"username"`
Firstname string `schema:"firstname"`
Lastname string `schema:"lastname"`
Language string `schema:"language"`
Password string `schema:"register-password"`
Password2 string `schema:"register-password-confirmation"`
TermsConfirm bool `schema:"terms-confirm"`
}
type registerData struct {

View File

@@ -94,7 +94,7 @@ func (l *Login) passLoginHintToRegistration(r *http.Request, authReq *domain.Aut
if authReq == nil {
return data
}
data.Email = authReq.LoginHint
data.Email = domain.EmailAddress(authReq.LoginHint)
domainPolicy, err := l.getOrgDomainPolicy(r, authReq.RequestedOrgID)
if err != nil {
logging.WithFields("authRequest", authReq.ID, "org", authReq.RequestedOrgID).Error("unable to load domain policy for registration loginHint")

View File

@@ -14,14 +14,14 @@ const (
)
type registerOrgFormData struct {
RegisterOrgName string `schema:"orgname"`
Email string `schema:"email"`
Username string `schema:"username"`
Firstname string `schema:"firstname"`
Lastname string `schema:"lastname"`
Password string `schema:"register-password"`
Password2 string `schema:"register-password-confirmation"`
TermsConfirm bool `schema:"terms-confirm"`
RegisterOrgName string `schema:"orgname"`
Email domain.EmailAddress `schema:"email"`
Username string `schema:"username"`
Firstname string `schema:"firstname"`
Lastname string `schema:"lastname"`
Password string `schema:"register-password"`
Password2 string `schema:"register-password-confirmation"`
TermsConfirm bool `schema:"terms-confirm"`
}
type registerOrgData struct {
@@ -121,7 +121,7 @@ func (l *Login) renderRegisterOrg(w http.ResponseWriter, r *http.Request, authRe
func (d registerOrgFormData) toUserDomain() *domain.Human {
if d.Username == "" {
d.Username = d.Email
d.Username = string(d.Email)
}
return &domain.Human{
Username: d.Username,
@@ -140,7 +140,7 @@ func (d registerOrgFormData) toUserDomain() *domain.Human {
func (d registerOrgFormData) toCommandOrg() *command.OrgSetup {
if d.Username == "" {
d.Username = d.Email
d.Username = string(d.Email)
}
return &command.OrgSetup{
Name: d.RegisterOrgName,

View File

@@ -328,6 +328,33 @@ Errors:
Invalid: Userdaten sind ungültig
DomainNotAllowedAsUsername: Domäne ist bereits reserviert und kann nicht verwendet werden
NotAllowedToLink: Der Benutzer darf nicht mit einem externen Login Provider verlinkt werden
Profile:
NotFound: Profil nicht gefunden
NotChanged: Profil nicht verändert
Empty: Profil ist leer
FirstNameEmpty: Vorname im Profil ist leer
LastNameEmpty: Nachname im Profil ist leer
IDMissing: Profil ID fehlt
Email:
NotFound: Email nicht gefunden
Invalid: Email ist ungültig
AlreadyVerified: Email ist bereits verifiziert
NotChanged: Email wurde nicht geändert
Empty: Email ist leer
IDMissing: Email ID fehlt
Phone:
NotFound: Telefonnummer nicht gefunden
Invalid: Telefonnummer ist ungültig
AlreadyVerified: Telefonnummer bereits verifiziert
Empty: Telefonnummer ist leer
NotChanged: Telefonnummer wurde nicht geändert
Address:
NotFound: Adresse nicht gefunden
NotChanged: Adresse wurde nicht geändert
Username:
AlreadyExists: Benutzername ist bereits vergeben
Reserved: Benutzername ist bereits vergeben
Empty: Benutzername ist leer
Password:
ConfirmationWrong: Passwort Bestätigung stimmt nicht überein
Empty: Passwort ist leer

View File

@@ -328,6 +328,33 @@ Errors:
Invalid: Invalid userdata
DomainNotAllowedAsUsername: Domain is already reserved and cannot be used
NotAllowedToLink: User is not allowed to link with external login provider
Profile:
NotFound: Profile not found
NotChanged: Profile not changed
Empty: Profile is empty
FirstNameEmpty: First name in profile is empty
LastNameEmpty: Last name in profile is empty
IDMissing: Profile ID is missing
Email:
NotFound: Email not found
Invalid: Email is invalid
AlreadyVerified: Email is already verified
NotChanged: Email not changed
Empty: Email is empty
IDMissing: Email ID is missing
Phone:
NotFound: Phone not found
Invalid: Phone is invalid
AlreadyVerified: Phone already verified
Empty: Phone is empty
NotChanged: Phone not changed
Address:
NotFound: Address not found
NotChanged: Address not changed
Username:
AlreadyExists: Username already taken
Reserved: Username is already taken
Empty: Username is empty
Password:
ConfirmationWrong: Passwordconfirmation is wrong
Empty: Password is empty

View File

@@ -328,6 +328,33 @@ Errors:
Invalid: Données utilisateur non valides
DomainNotAllowedAsUsername: Le domaine est déjà réservé et ne peut pas être utilisé.
NotAllowedToLink: L'utilisateur n'est pas autorisé à établir un lien avec un fournisseur de connexion externe
Profile:
NotFound: Profil non trouvé
NotChanged: Le profil n'a pas changé
Empty: Profil est vide
FirstNameEmpty: Le prénom dans le profil est vide
LastNameEmpty: Le nom de famille dans le profil est vide
IDMissing: Profil ID manquant
Email:
NotFound: Email non trouvé
Invalid: L'email n'est pas valide
AlreadyVerified: L'adresse électronique est déjà vérifiée
NotChanged: L'adresse électronique n'a pas changé
Empty: Email est vide
IDMissing: Email ID manquant
Phone:
Notfound: Téléphone non trouvé
Invalid: Le téléphone n'est pas valide
AlreadyVerified: Téléphone déjà vérifié
Empty: Téléphone est vide
NotChanged: Téléphone n'a pas changé
Address:
NotFound: Adresse non trouvée
NotChanged: L'adresse n'a pas changé
Username:
AlreadyExists: Nom d'utilisateur déjà pris
Reserved: Le nom d'utilisateur est déjà pris
Empty: Le nom d'utilisateur est vide
Password:
ConfirmationWrong: La confirmation du mot de passe est erronée
Empty: Le mot de passe est vide

View File

@@ -328,6 +328,33 @@ Errors:
Invalid: I dati del utente non sono validi
DomainNotAllowedAsUsername: Il dominio è già riservato e non può essere utilizzato
NotAllowedToLink: L'utente non è autorizzato a collegarsi con un provider di accesso esterno
Profile:
NotFound: Profilo non trovato
NotChanged: Profilo non cambiato
Empty: Profilo è vuoto
FirstNameEmpty: Il nome nel profilo è vuoto
LastNameEmpty: Il cognome nel profilo è vuoto
IDMissing: Profilo ID mancante
Email:
NotFound: Email non trovata
Invalid: L'e-mail non è valida
AlreadyVerified: L'e-mail è già verificata
NotChanged: Email non cambiata
Empty: Email è vuota
IDMissing: Email ID mancante
Phone:
NotFound: Telefono non trovato
Invalid: Il telefono non è valido
AlreadyVerified: Telefono già verificato
Empty: Il telefono è vuoto
NotChanged: Telefono non cambiato
Address:
NotFound: Indirizzo non trovato
NotChanged: Indirizzo non cambiato
Username:
AlreadyExists: Nome utente già preso
Reserved: Il nome utente è già preso
Empty: Il nome utente è vuoto
Password:
ConfirmationWrong: La conferma della password è sbagliata
Empty: La password è vuota

View File

@@ -328,6 +328,33 @@ Errors:
Invalid: Nieprawidłowe dane użytkownika
DomainNotAllowedAsUsername: Domena jest już zarezerwowana i nie może być użyta
NotAllowedToLink: Użytkownik nie jest upoważniony do łączenia z zewnętrznym dostawcą logowania
Profile:
NotFound: Profil nie znaleziony
NotChanged: Profil nie zmieniony
Empty: Profil jest pusty
FirstNameEmpty: Imię w profilu jest puste
LastNameEmpty: Nazwisko w profilu jest puste
IDMissing: Profil ID brakuje
Email:
NotFound: Adres e-mail nie znaleziony
Invalid: Adres e-mail jest nieprawidłowy
AlreadyVerified: Adres e-mail jest już zweryfikowany
NotChanged: Adres e-mail nie zmieniony
Empty: Adres e-mail jest pusty
IDMissing: Adres e-mail ID brakuje
Phone:
NotFound: Numer telefonu nie znaleziony
Invalid: Numer telefonu jest nieprawidłowy
AlreadyVerified: Numer telefonu już zweryfikowany
Empty: Numer telefonu jest pusty
NotChanged: Numer telefonu nie zmieniony
Address:
NotFound: Adres nie znaleziony
NotChanged: Adres nie zmieniony
Username:
AlreadyExists: Nazwa użytkownika jest już zajęta
Reserved: Nazwa użytkownika jest już zajęta
Empty: Nazwa użytkownika jest pusty
Password:
ConfirmationWrong: Potwierdzenie hasła jest niepoprawne
Empty: Hasło jest puste

View File

@@ -328,6 +328,33 @@ Errors:
Invalid: 无效的用户数据
DomainNotAllowedAsUsername: 域名已存在,但无法使用
NotAllowedToLink: 不允许用户使用外部身份提供者注册
Profile:
NotFound: 未找到个人资料
NotChanged: 个人资料未更改
Empty: 简介是空的
FirstNameEmpty: 简介中的名字是空的
LastNameEmpty: 简介中的姓氏是空的
IDMissing: 简介ID丢失
Email:
NotFound: 电子邮件没有找到
Invalid: 电子邮件无效
AlreadyVerified: 电子邮件已经过验证
NotChanged: 电子邮件未更改
Empty: 电子邮件是空的
IDMissing: 电子邮件ID丢失
Phone:
NotFound: 手机号码未找到
Invalid: 手机号码无效
AlreadyVerified: 手机号码已经验证
Empty: 电话号码是空的
NotChanged: 电话号码没有改变
Address:
NotFound: 找不到地址
NotChanged: 地址没有改变
Username:
AlreadyExists: 用户名已被使用
Reserved: 用户名已被使用
Empty: 用户名是空的
Password:
ConfirmationWrong: 密码不一致
Empty: 密码为空