zitadel/internal/ui/login/handler/register_handler.go
Fabi 99b2c33ccb
feat: Custom text login (#1925)
* feat: default custom message text

* feat: org custom message text

* feat: org custom message text

* feat: custom messages query side

* feat: default messages

* feat: message text user fields

* feat: check for inactive user

* feat: fix send password reset

* feat: fix custom org text

* feat: add variables to docs

* feat: custom text tests

* feat: fix notifications

* feat: add custom text feature

* feat: add custom text feature

* feat: feature in custom message texts

* feat: add custom text feature in frontend

* feat: merge main

* feat: feature tests

* feat: change phone message in setup

* fix: remove unused code, add event translation

* fix: merge main and fix problems

* fix: english translation file

* fix: migration versions

* fix: setup

* fix: custom login text

* feat: add all possible custom texts for login

* feat: iam login texts

* feat: org login texts

* feat: protos

* fix: custom text in admin api

* fix: add success login text

* fix: docs

* fix: add custom login texts to management api

* fix: add sub messages to custom login texts

* fix: setup custom texts

* feat: get org login texts

* feat: get org login texts

* feat: handler in adminapi

* feat: handlers in auth and admin

* feat: render login texts

* feat: custom login text

* feat: add all login text keys

* feat: handle correct login texts

* feat: custom login texts in command side

* feat: custom login texts in command side

* feat: fix yaml file

* feat: merge master and add confirmation text

* feat: fix html

* feat: read default login texts

* feat: get default text files

* feat: get custom texts org

* feat: tests

* feat: change translator handling

* fix translator from authReq

* feat: change h1 on login screens

* feat: add custom login text for remove

* feat: add custom login text for remove

* feat: cache translation files

* feat: cache translation files

* feat: zitadel user in env var

* feat: add registration user description

* feat: better func naming

* feat: tests

* feat: add mutex to read file

* feat: add mutex to read file

* fix mutex for accessing translation map

* fix: translation key

Co-authored-by: Livio Amstutz <livio.a@gmail.com>
2021-07-05 15:10:49 +02:00

183 lines
4.9 KiB
Go

package handler
import (
"net/http"
"golang.org/x/text/language"
http_mw "github.com/caos/zitadel/internal/api/http/middleware"
"github.com/caos/zitadel/internal/domain"
caos_errs "github.com/caos/zitadel/internal/errors"
)
const (
tmplRegister = "register"
)
type registerFormData struct {
Email string `schema:"email"`
Username string `schema:"username"`
Firstname string `schema:"firstname"`
Lastname string `schema:"lastname"`
Language string `schema:"language"`
Gender int32 `schema:"gender"`
Password string `schema:"register-password"`
Password2 string `schema:"register-password-confirmation"`
TermsConfirm bool `schema:"terms-confirm"`
}
type registerData struct {
baseData
registerFormData
PasswordPolicyDescription string
MinLength uint64
HasUppercase string
HasLowercase string
HasNumber string
HasSymbol string
ShowUsername bool
OrgRegister bool
}
func (l *Login) handleRegister(w http.ResponseWriter, r *http.Request) {
data := new(registerFormData)
authRequest, err := l.getAuthRequestAndParseData(r, data)
if err != nil {
l.renderError(w, r, authRequest, err)
return
}
l.renderRegister(w, r, authRequest, data, nil)
}
func (l *Login) handleRegisterCheck(w http.ResponseWriter, r *http.Request) {
data := new(registerFormData)
authRequest, err := l.getAuthRequestAndParseData(r, data)
if err != nil {
l.renderError(w, r, authRequest, err)
return
}
if data.Password != data.Password2 {
err := caos_errs.ThrowInvalidArgument(nil, "VIEW-KaGue", "Errors.User.Password.ConfirmationWrong")
l.renderRegister(w, r, authRequest, data, err)
return
}
iam, err := l.authRepo.GetIAM(r.Context())
if err != nil {
l.renderRegister(w, r, authRequest, data, err)
return
}
resourceOwner := iam.GlobalOrgID
memberRoles := []string{domain.RoleOrgProjectCreator}
if authRequest.RequestedOrgID != "" && authRequest.RequestedOrgID != iam.GlobalOrgID {
memberRoles = nil
resourceOwner = authRequest.RequestedOrgID
}
user, err := l.command.RegisterHuman(setContext(r.Context(), resourceOwner), resourceOwner, data.toHumanDomain(), nil, memberRoles)
if err != nil {
l.renderRegister(w, r, authRequest, data, err)
return
}
if authRequest == nil {
http.Redirect(w, r, l.zitadelURL, http.StatusFound)
return
}
userAgentID, _ := http_mw.UserAgentIDFromCtx(r.Context())
err = l.authRepo.SelectUser(r.Context(), authRequest.ID, user.AggregateID, userAgentID)
if err != nil {
l.renderRegister(w, r, authRequest, data, err)
return
}
l.renderNextStep(w, r, authRequest)
}
func (l *Login) renderRegister(w http.ResponseWriter, r *http.Request, authRequest *domain.AuthRequest, formData *registerFormData, err error) {
var errID, errMessage string
if err != nil {
errID, errMessage = l.getErrorMessage(r, err)
}
translator := l.getTranslator(authRequest)
if formData == nil {
formData = new(registerFormData)
}
if formData.Language == "" {
formData.Language = l.renderer.ReqLang(translator, r).String()
}
data := registerData{
baseData: l.getBaseData(r, authRequest, "Register", errID, errMessage),
registerFormData: *formData,
}
resourceOwner := authRequest.RequestedOrgID
if resourceOwner == "" {
iam, err := l.authRepo.GetIAM(r.Context())
if err != nil {
l.renderRegister(w, r, authRequest, formData, err)
return
}
resourceOwner = iam.GlobalOrgID
}
pwPolicy, description, _ := l.getPasswordComplexityPolicy(r, authRequest, resourceOwner)
if pwPolicy != nil {
data.PasswordPolicyDescription = description
data.MinLength = pwPolicy.MinLength
if pwPolicy.HasUppercase {
data.HasUppercase = UpperCaseRegex
}
if pwPolicy.HasLowercase {
data.HasLowercase = LowerCaseRegex
}
if pwPolicy.HasSymbol {
data.HasSymbol = SymbolRegex
}
if pwPolicy.HasNumber {
data.HasNumber = NumberRegex
}
}
orgIAMPolicy, err := l.getOrgIamPolicy(r, resourceOwner)
if err != nil {
l.renderRegister(w, r, authRequest, formData, err)
return
}
data.ShowUsername = orgIAMPolicy.UserLoginMustBeDomain
data.OrgRegister = orgIAMPolicy.UserLoginMustBeDomain
funcs := map[string]interface{}{
"selectedLanguage": func(l string) bool {
if formData == nil {
return false
}
return formData.Language == l
},
"selectedGender": func(g int32) bool {
if formData == nil {
return false
}
return formData.Gender == g
},
}
l.renderer.RenderTemplate(w, r, translator, l.renderer.Templates[tmplRegister], data, funcs)
}
func (d registerFormData) toHumanDomain() *domain.Human {
return &domain.Human{
Username: d.Username,
Profile: &domain.Profile{
FirstName: d.Firstname,
LastName: d.Lastname,
PreferredLanguage: language.Make(d.Language),
Gender: domain.Gender(d.Gender),
},
Password: &domain.Password{
SecretString: d.Password,
},
Email: &domain.Email{
EmailAddress: d.Email,
},
}
}