mirror of
https://github.com/zitadel/zitadel.git
synced 2024-12-13 03:24:26 +00:00
e4a4b7cfbe
* chore(proto): update versions
* change protoc plugin
* some cleanups
* define api for setting emails in new api
* implement user.SetEmail
* move SetEmail buisiness logic into command
* resuse newCryptoCode
* command: add ChangeEmail unit tests
Not complete, was not able to mock the generator.
* Revert "resuse newCryptoCode"
This reverts commit c89e90ae35
.
* undo change to crypto code generators
* command: use a generator so we can test properly
* command: reorganise ChangeEmail
improve test coverage
* implement VerifyEmail
including unit tests
* add URL template tests
* begin user creation
* change protos
* implement metadata and move context
* merge commands
* proto: change context to object
* remove old auth option
* remove old auth option
* fix linting errors
run gci on modified files
* add permission checks and fix some errors
* comments
* comments
* update email requests
* rename proto requests
* cleanup and docs
* simplify
* simplify
* fix setup
* remove unused proto messages / fields
---------
Co-authored-by: adlerhurst <silvan.reusser@gmail.com>
Co-authored-by: Tim Möhlmann <tim+github@zitadel.com>
108 lines
3.5 KiB
Go
108 lines
3.5 KiB
Go
package user
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
|
|
"golang.org/x/text/language"
|
|
|
|
"github.com/zitadel/zitadel/internal/api/grpc/object/v2"
|
|
"github.com/zitadel/zitadel/internal/command"
|
|
"github.com/zitadel/zitadel/internal/domain"
|
|
"github.com/zitadel/zitadel/internal/errors"
|
|
"github.com/zitadel/zitadel/pkg/grpc/user/v2alpha"
|
|
)
|
|
|
|
func (s *Server) AddHumanUser(ctx context.Context, req *user.AddHumanUserRequest) (_ *user.AddHumanUserResponse, err error) {
|
|
human, err := addUserRequestToAddHuman(req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
err = s.command.AddHuman(ctx, req.GetOrganisation().GetOrgId(), human, false)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &user.AddHumanUserResponse{
|
|
UserId: human.ID,
|
|
Details: object.DomainToDetailsPb(human.Details),
|
|
EmailCode: human.EmailCode,
|
|
}, nil
|
|
}
|
|
|
|
func addUserRequestToAddHuman(req *user.AddHumanUserRequest) (*command.AddHuman, error) {
|
|
username := req.GetUsername()
|
|
if username == "" {
|
|
username = req.GetEmail().GetEmail()
|
|
}
|
|
var urlTemplate string
|
|
if req.GetEmail().GetSendCode() != nil {
|
|
urlTemplate = req.GetEmail().GetSendCode().GetUrlTemplate()
|
|
// test the template execution so the async notification will not fail because of it and the user won't realize
|
|
if err := domain.RenderConfirmURLTemplate(io.Discard, urlTemplate, req.GetUserId(), "code", "orgID"); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
bcryptedPassword, err := hashedPasswordToCommand(req.GetHashedPassword())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
passwordChangeRequired := req.GetPassword().GetChangeRequired() || req.GetHashedPassword().GetChangeRequired()
|
|
metadata := make([]*command.AddMetadataEntry, len(req.Metadata))
|
|
for i, metadataEntry := range req.Metadata {
|
|
metadata[i] = &command.AddMetadataEntry{
|
|
Key: metadataEntry.GetKey(),
|
|
Value: metadataEntry.GetValue(),
|
|
}
|
|
}
|
|
return &command.AddHuman{
|
|
ID: req.GetUserId(),
|
|
Username: username,
|
|
FirstName: req.GetProfile().GetFirstName(),
|
|
LastName: req.GetProfile().GetLastName(),
|
|
NickName: req.GetProfile().GetNickName(),
|
|
DisplayName: req.GetProfile().GetDisplayName(),
|
|
Email: command.Email{
|
|
Address: domain.EmailAddress(req.GetEmail().GetEmail()),
|
|
Verified: req.GetEmail().GetIsVerified(),
|
|
ReturnCode: req.GetEmail().GetReturnCode() != nil,
|
|
URLTemplate: urlTemplate,
|
|
},
|
|
PreferredLanguage: language.Make(req.GetProfile().GetPreferredLanguage()),
|
|
Gender: genderToDomain(req.GetProfile().GetGender()),
|
|
Phone: command.Phone{}, // TODO: add as soon as possible
|
|
Password: req.GetPassword().GetPassword(),
|
|
BcryptedPassword: bcryptedPassword,
|
|
PasswordChangeRequired: passwordChangeRequired,
|
|
Passwordless: false,
|
|
ExternalIDP: false,
|
|
Register: false,
|
|
Metadata: metadata,
|
|
}, nil
|
|
}
|
|
|
|
func genderToDomain(gender user.Gender) domain.Gender {
|
|
switch gender {
|
|
case user.Gender_GENDER_UNSPECIFIED:
|
|
return domain.GenderUnspecified
|
|
case user.Gender_GENDER_FEMALE:
|
|
return domain.GenderFemale
|
|
case user.Gender_GENDER_MALE:
|
|
return domain.GenderMale
|
|
case user.Gender_GENDER_DIVERSE:
|
|
return domain.GenderDiverse
|
|
default:
|
|
return domain.GenderUnspecified
|
|
}
|
|
}
|
|
|
|
func hashedPasswordToCommand(hashed *user.HashedPassword) (string, error) {
|
|
if hashed == nil {
|
|
return "", nil
|
|
}
|
|
// we currently only handle bcrypt
|
|
if hashed.GetAlgorithm() != "bcrypt" {
|
|
return "", errors.ThrowInvalidArgument(nil, "USER-JDk4t", "Errors.InvalidArgument")
|
|
}
|
|
return hashed.GetHash(), nil
|
|
}
|