mirror of
https://github.com/zitadel/zitadel.git
synced 2025-02-28 20:57:24 +00:00
feat: New event user (#1156)
* feat: change user command side * feat: change user command side * feat: use states on write model * feat: command and query side in auth api * feat: auth commands * feat: check external idp id * feat: user state check * fix: error messages * fix: is active state
This commit is contained in:
parent
65a8efeb0e
commit
26c8113930
@ -162,7 +162,7 @@ func startAPI(ctx context.Context, conf *Config, authZRepo *authz_repo.EsReposit
|
|||||||
apis.RegisterServer(ctx, management.CreateServer(command, query, managementRepo, conf.SystemDefaults))
|
apis.RegisterServer(ctx, management.CreateServer(command, query, managementRepo, conf.SystemDefaults))
|
||||||
}
|
}
|
||||||
if *authEnabled {
|
if *authEnabled {
|
||||||
apis.RegisterServer(ctx, auth.CreateServer(authRepo))
|
apis.RegisterServer(ctx, auth.CreateServer(command, query, authRepo))
|
||||||
}
|
}
|
||||||
if *oidcEnabled {
|
if *oidcEnabled {
|
||||||
op := oidc.NewProvider(ctx, conf.API.OIDC, authRepo, *localDevMode)
|
op := oidc.NewProvider(ctx, conf.API.OIDC, authRepo, *localDevMode)
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package auth
|
package auth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/caos/zitadel/internal/v2/command"
|
||||||
|
"github.com/caos/zitadel/internal/v2/query"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
|
|
||||||
"github.com/caos/zitadel/internal/api/authz"
|
"github.com/caos/zitadel/internal/api/authz"
|
||||||
@ -17,16 +19,20 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
repo repository.Repository
|
command *command.CommandSide
|
||||||
|
query *query.QuerySide
|
||||||
|
repo repository.Repository
|
||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Repository eventsourcing.Config
|
Repository eventsourcing.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateServer(authRepo repository.Repository) *Server {
|
func CreateServer(command *command.CommandSide, query *query.QuerySide, authRepo repository.Repository) *Server {
|
||||||
return &Server{
|
return &Server{
|
||||||
repo: authRepo,
|
command: command,
|
||||||
|
query: query,
|
||||||
|
repo: authRepo,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ package auth
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"github.com/caos/zitadel/internal/api/authz"
|
||||||
"github.com/golang/protobuf/ptypes/empty"
|
"github.com/golang/protobuf/ptypes/empty"
|
||||||
|
|
||||||
"github.com/caos/zitadel/pkg/grpc/auth"
|
"github.com/caos/zitadel/pkg/grpc/auth"
|
||||||
@ -62,23 +62,24 @@ func (s *Server) GetMyMfas(ctx context.Context, _ *empty.Empty) (*auth.MultiFact
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) UpdateMyUserProfile(ctx context.Context, request *auth.UpdateUserProfileRequest) (*auth.UserProfile, error) {
|
func (s *Server) UpdateMyUserProfile(ctx context.Context, request *auth.UpdateUserProfileRequest) (*auth.UserProfile, error) {
|
||||||
profile, err := s.repo.ChangeMyProfile(ctx, updateProfileToModel(ctx, request))
|
profile, err := s.command.ChangeHumanProfile(ctx, updateProfileToDomain(ctx, request))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return profileFromModel(profile), nil
|
return profileFromDomain(profile), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) ChangeMyUserName(ctx context.Context, request *auth.ChangeUserNameRequest) (*empty.Empty, error) {
|
func (s *Server) ChangeMyUserName(ctx context.Context, request *auth.ChangeUserNameRequest) (*empty.Empty, error) {
|
||||||
return &empty.Empty{}, s.repo.ChangeMyUsername(ctx, request.UserName)
|
ctxData := authz.GetCtxData(ctx)
|
||||||
|
return &empty.Empty{}, s.command.ChangeUsername(ctx, ctxData.OrgID, ctxData.UserID, request.UserName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) ChangeMyUserEmail(ctx context.Context, request *auth.UpdateUserEmailRequest) (*auth.UserEmail, error) {
|
func (s *Server) ChangeMyUserEmail(ctx context.Context, request *auth.UpdateUserEmailRequest) (*auth.UserEmail, error) {
|
||||||
email, err := s.repo.ChangeMyEmail(ctx, updateEmailToModel(ctx, request))
|
email, err := s.command.ChangeHumanEmail(ctx, updateEmailToDomain(ctx, request))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return emailFromModel(email), nil
|
return emailFromDomain(email), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) VerifyMyUserEmail(ctx context.Context, request *auth.VerifyMyUserEmailRequest) (*empty.Empty, error) {
|
func (s *Server) VerifyMyUserEmail(ctx context.Context, request *auth.VerifyMyUserEmailRequest) (*empty.Empty, error) {
|
||||||
@ -92,11 +93,11 @@ func (s *Server) ResendMyEmailVerificationMail(ctx context.Context, _ *empty.Emp
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) ChangeMyUserPhone(ctx context.Context, request *auth.UpdateUserPhoneRequest) (*auth.UserPhone, error) {
|
func (s *Server) ChangeMyUserPhone(ctx context.Context, request *auth.UpdateUserPhoneRequest) (*auth.UserPhone, error) {
|
||||||
phone, err := s.repo.ChangeMyPhone(ctx, updatePhoneToModel(ctx, request))
|
phone, err := s.command.ChangeHumanPhone(ctx, updatePhoneToDomain(ctx, request))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return phoneFromModel(phone), nil
|
return phoneFromDomain(phone), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) VerifyMyUserPhone(ctx context.Context, request *auth.VerifyUserPhoneRequest) (*empty.Empty, error) {
|
func (s *Server) VerifyMyUserPhone(ctx context.Context, request *auth.VerifyUserPhoneRequest) (*empty.Empty, error) {
|
||||||
|
@ -3,6 +3,7 @@ package auth
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"github.com/caos/zitadel/internal/v2/domain"
|
||||||
|
|
||||||
"github.com/caos/logging"
|
"github.com/caos/logging"
|
||||||
"github.com/golang/protobuf/ptypes"
|
"github.com/golang/protobuf/ptypes"
|
||||||
@ -52,7 +53,7 @@ func userViewFromModel(user *usr_model.UserView) *auth.UserView {
|
|||||||
return userView
|
return userView
|
||||||
}
|
}
|
||||||
|
|
||||||
func profileFromModel(profile *usr_model.Profile) *auth.UserProfile {
|
func profileFromDomain(profile *domain.Profile) *auth.UserProfile {
|
||||||
creationDate, err := ptypes.TimestampProto(profile.CreationDate)
|
creationDate, err := ptypes.TimestampProto(profile.CreationDate)
|
||||||
logging.Log("GRPC-56t5s").OnError(err).Debug("unable to parse timestamp")
|
logging.Log("GRPC-56t5s").OnError(err).Debug("unable to parse timestamp")
|
||||||
|
|
||||||
@ -69,7 +70,7 @@ func profileFromModel(profile *usr_model.Profile) *auth.UserProfile {
|
|||||||
DisplayName: profile.DisplayName,
|
DisplayName: profile.DisplayName,
|
||||||
NickName: profile.NickName,
|
NickName: profile.NickName,
|
||||||
PreferredLanguage: profile.PreferredLanguage.String(),
|
PreferredLanguage: profile.PreferredLanguage.String(),
|
||||||
Gender: genderFromModel(profile.Gender),
|
Gender: genderFromDomain(profile.Gender),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,36 +82,37 @@ func profileViewFromModel(profile *usr_model.Profile) *auth.UserProfileView {
|
|||||||
logging.Log("GRPC-9sujE").OnError(err).Debug("unable to parse timestamp")
|
logging.Log("GRPC-9sujE").OnError(err).Debug("unable to parse timestamp")
|
||||||
|
|
||||||
return &auth.UserProfileView{
|
return &auth.UserProfileView{
|
||||||
Id: profile.AggregateID,
|
Id: profile.AggregateID,
|
||||||
CreationDate: creationDate,
|
CreationDate: creationDate,
|
||||||
ChangeDate: changeDate,
|
ChangeDate: changeDate,
|
||||||
Sequence: profile.Sequence,
|
Sequence: profile.Sequence,
|
||||||
FirstName: profile.FirstName,
|
FirstName: profile.FirstName,
|
||||||
LastName: profile.LastName,
|
LastName: profile.LastName,
|
||||||
DisplayName: profile.DisplayName,
|
DisplayName: profile.DisplayName,
|
||||||
NickName: profile.NickName,
|
NickName: profile.NickName,
|
||||||
PreferredLanguage: profile.PreferredLanguage.String(),
|
PreferredLanguage: profile.PreferredLanguage.String(),
|
||||||
Gender: genderFromModel(profile.Gender),
|
//TODO: Use converter
|
||||||
|
Gender: auth.Gender(profile.Gender),
|
||||||
LoginNames: profile.LoginNames,
|
LoginNames: profile.LoginNames,
|
||||||
PreferredLoginName: profile.PreferredLoginName,
|
PreferredLoginName: profile.PreferredLoginName,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateProfileToModel(ctx context.Context, u *auth.UpdateUserProfileRequest) *usr_model.Profile {
|
func updateProfileToDomain(ctx context.Context, u *auth.UpdateUserProfileRequest) *domain.Profile {
|
||||||
preferredLanguage, err := language.Parse(u.PreferredLanguage)
|
preferredLanguage, err := language.Parse(u.PreferredLanguage)
|
||||||
logging.Log("GRPC-lk73L").OnError(err).WithField("traceID", tracing.TraceIDFromCtx(ctx)).Debug("language malformed")
|
logging.Log("GRPC-lk73L").OnError(err).WithField("traceID", tracing.TraceIDFromCtx(ctx)).Debug("language malformed")
|
||||||
|
|
||||||
return &usr_model.Profile{
|
return &domain.Profile{
|
||||||
ObjectRoot: models.ObjectRoot{AggregateID: authz.GetCtxData(ctx).UserID},
|
ObjectRoot: models.ObjectRoot{AggregateID: authz.GetCtxData(ctx).UserID},
|
||||||
FirstName: u.FirstName,
|
FirstName: u.FirstName,
|
||||||
LastName: u.LastName,
|
LastName: u.LastName,
|
||||||
NickName: u.NickName,
|
NickName: u.NickName,
|
||||||
PreferredLanguage: preferredLanguage,
|
PreferredLanguage: preferredLanguage,
|
||||||
Gender: genderToModel(u.Gender),
|
Gender: genderToDomain(u.Gender),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func emailFromModel(email *usr_model.Email) *auth.UserEmail {
|
func emailFromDomain(email *domain.Email) *auth.UserEmail {
|
||||||
creationDate, err := ptypes.TimestampProto(email.CreationDate)
|
creationDate, err := ptypes.TimestampProto(email.CreationDate)
|
||||||
logging.Log("GRPC-sdoi3").OnError(err).Debug("unable to parse timestamp")
|
logging.Log("GRPC-sdoi3").OnError(err).Debug("unable to parse timestamp")
|
||||||
|
|
||||||
@ -144,14 +146,14 @@ func emailViewFromModel(email *usr_model.Email) *auth.UserEmailView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateEmailToModel(ctx context.Context, e *auth.UpdateUserEmailRequest) *usr_model.Email {
|
func updateEmailToDomain(ctx context.Context, e *auth.UpdateUserEmailRequest) *domain.Email {
|
||||||
return &usr_model.Email{
|
return &domain.Email{
|
||||||
ObjectRoot: models.ObjectRoot{AggregateID: authz.GetCtxData(ctx).UserID},
|
ObjectRoot: models.ObjectRoot{AggregateID: authz.GetCtxData(ctx).UserID},
|
||||||
EmailAddress: e.Email,
|
EmailAddress: e.Email,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func phoneFromModel(phone *usr_model.Phone) *auth.UserPhone {
|
func phoneFromDomain(phone *domain.Phone) *auth.UserPhone {
|
||||||
creationDate, err := ptypes.TimestampProto(phone.CreationDate)
|
creationDate, err := ptypes.TimestampProto(phone.CreationDate)
|
||||||
logging.Log("GRPC-kjn5J").OnError(err).Debug("unable to parse timestamp")
|
logging.Log("GRPC-kjn5J").OnError(err).Debug("unable to parse timestamp")
|
||||||
|
|
||||||
@ -185,8 +187,8 @@ func phoneViewFromModel(phone *usr_model.Phone) *auth.UserPhoneView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func updatePhoneToModel(ctx context.Context, e *auth.UpdateUserPhoneRequest) *usr_model.Phone {
|
func updatePhoneToDomain(ctx context.Context, e *auth.UpdateUserPhoneRequest) *domain.Phone {
|
||||||
return &usr_model.Phone{
|
return &domain.Phone{
|
||||||
ObjectRoot: models.ObjectRoot{AggregateID: authz.GetCtxData(ctx).UserID},
|
ObjectRoot: models.ObjectRoot{AggregateID: authz.GetCtxData(ctx).UserID},
|
||||||
PhoneNumber: e.Phone,
|
PhoneNumber: e.Phone,
|
||||||
}
|
}
|
||||||
@ -332,29 +334,29 @@ func userStateFromModel(state usr_model.UserState) auth.UserState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func genderFromModel(gender usr_model.Gender) auth.Gender {
|
func genderFromDomain(gender domain.Gender) auth.Gender {
|
||||||
switch gender {
|
switch gender {
|
||||||
case usr_model.GenderFemale:
|
case domain.GenderFemale:
|
||||||
return auth.Gender_GENDER_FEMALE
|
return auth.Gender_GENDER_FEMALE
|
||||||
case usr_model.GenderMale:
|
case domain.GenderMale:
|
||||||
return auth.Gender_GENDER_MALE
|
return auth.Gender_GENDER_MALE
|
||||||
case usr_model.GenderDiverse:
|
case domain.GenderDiverse:
|
||||||
return auth.Gender_GENDER_DIVERSE
|
return auth.Gender_GENDER_DIVERSE
|
||||||
default:
|
default:
|
||||||
return auth.Gender_GENDER_UNSPECIFIED
|
return auth.Gender_GENDER_UNSPECIFIED
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func genderToModel(gender auth.Gender) usr_model.Gender {
|
func genderToDomain(gender auth.Gender) domain.Gender {
|
||||||
switch gender {
|
switch gender {
|
||||||
case auth.Gender_GENDER_FEMALE:
|
case auth.Gender_GENDER_FEMALE:
|
||||||
return usr_model.GenderFemale
|
return domain.GenderFemale
|
||||||
case auth.Gender_GENDER_MALE:
|
case auth.Gender_GENDER_MALE:
|
||||||
return usr_model.GenderMale
|
return domain.GenderMale
|
||||||
case auth.Gender_GENDER_DIVERSE:
|
case auth.Gender_GENDER_DIVERSE:
|
||||||
return usr_model.GenderDiverse
|
return domain.GenderDiverse
|
||||||
default:
|
default:
|
||||||
return usr_model.GenderUnspecified
|
return domain.GenderUnspecified
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,16 +17,17 @@ func humanViewFromModel(user *usr_model.HumanView) *auth.HumanView {
|
|||||||
DisplayName: user.DisplayName,
|
DisplayName: user.DisplayName,
|
||||||
NickName: user.NickName,
|
NickName: user.NickName,
|
||||||
PreferredLanguage: user.PreferredLanguage,
|
PreferredLanguage: user.PreferredLanguage,
|
||||||
Gender: genderFromModel(user.Gender),
|
//TODO: add converter
|
||||||
Email: user.Email,
|
Gender: auth.Gender(user.Gender),
|
||||||
IsEmailVerified: user.IsEmailVerified,
|
Email: user.Email,
|
||||||
Phone: user.Phone,
|
IsEmailVerified: user.IsEmailVerified,
|
||||||
IsPhoneVerified: user.IsPhoneVerified,
|
Phone: user.Phone,
|
||||||
Country: user.Country,
|
IsPhoneVerified: user.IsPhoneVerified,
|
||||||
Locality: user.Locality,
|
Country: user.Country,
|
||||||
PostalCode: user.PostalCode,
|
Locality: user.Locality,
|
||||||
Region: user.Region,
|
PostalCode: user.PostalCode,
|
||||||
StreetAddress: user.StreetAddress,
|
Region: user.Region,
|
||||||
PasswordChanged: passwordChanged,
|
StreetAddress: user.StreetAddress,
|
||||||
|
PasswordChanged: passwordChanged,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ func (s *Server) IsUserUnique(ctx context.Context, request *management.UniqueUse
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) CreateUser(ctx context.Context, in *management.CreateUserRequest) (*management.UserResponse, error) {
|
func (s *Server) CreateUser(ctx context.Context, in *management.CreateUserRequest) (*management.UserResponse, error) {
|
||||||
user, err := s.command.AddUser(ctx, userCreateToDomain(in))
|
user, err := s.command.AddUser(ctx, authz.GetCtxData(ctx).OrgID, userCreateToDomain(in))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -113,7 +113,7 @@ func (s *Server) GetUserProfile(ctx context.Context, in *management.UserID) (*ma
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) ChangeUserUserName(ctx context.Context, request *management.UpdateUserUserNameRequest) (*empty.Empty, error) {
|
func (s *Server) ChangeUserUserName(ctx context.Context, request *management.UpdateUserUserNameRequest) (*empty.Empty, error) {
|
||||||
return &empty.Empty{}, s.user.ChangeUsername(ctx, request.Id, request.UserName)
|
return &empty.Empty{}, s.command.ChangeUsername(ctx, authz.GetCtxData(ctx).OrgID, request.Id, request.UserName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) UpdateUserProfile(ctx context.Context, request *management.UpdateUserProfileRequest) (*management.UserProfile, error) {
|
func (s *Server) UpdateUserProfile(ctx context.Context, request *management.UpdateUserProfileRequest) (*management.UserProfile, error) {
|
||||||
@ -141,7 +141,7 @@ func (s *Server) ChangeUserEmail(ctx context.Context, request *management.Update
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) ResendEmailVerificationMail(ctx context.Context, in *management.UserID) (*empty.Empty, error) {
|
func (s *Server) ResendEmailVerificationMail(ctx context.Context, in *management.UserID) (*empty.Empty, error) {
|
||||||
err := s.user.CreateEmailVerificationCode(ctx, in.Id)
|
err := s.command.CreateHumanEmailVerificationCode(ctx, in.Id)
|
||||||
return &empty.Empty{}, err
|
return &empty.Empty{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,20 +154,20 @@ func (s *Server) GetUserPhone(ctx context.Context, in *management.UserID) (*mana
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) ChangeUserPhone(ctx context.Context, request *management.UpdateUserPhoneRequest) (*management.UserPhone, error) {
|
func (s *Server) ChangeUserPhone(ctx context.Context, request *management.UpdateUserPhoneRequest) (*management.UserPhone, error) {
|
||||||
phone, err := s.user.ChangePhone(ctx, updatePhoneToModel(request))
|
phone, err := s.command.ChangeHumanPhone(ctx, updatePhoneToDomain(request))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return phoneFromModel(phone), nil
|
return phoneFromDomain(phone), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) RemoveUserPhone(ctx context.Context, userID *management.UserID) (*empty.Empty, error) {
|
func (s *Server) RemoveUserPhone(ctx context.Context, userID *management.UserID) (*empty.Empty, error) {
|
||||||
err := s.user.RemovePhone(ctx, userID.Id)
|
err := s.command.RemoveHumanPhone(ctx, userID.Id)
|
||||||
return &empty.Empty{}, err
|
return &empty.Empty{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) ResendPhoneVerificationCode(ctx context.Context, in *management.UserID) (*empty.Empty, error) {
|
func (s *Server) ResendPhoneVerificationCode(ctx context.Context, in *management.UserID) (*empty.Empty, error) {
|
||||||
err := s.user.CreatePhoneVerificationCode(ctx, in.Id)
|
err := s.command.CreateHumanPhoneVerificationCode(ctx, in.Id)
|
||||||
return &empty.Empty{}, err
|
return &empty.Empty{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,18 +188,16 @@ func (s *Server) UpdateUserAddress(ctx context.Context, request *management.Upda
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) SendSetPasswordNotification(ctx context.Context, request *management.SetPasswordNotificationRequest) (*empty.Empty, error) {
|
func (s *Server) SendSetPasswordNotification(ctx context.Context, request *management.SetPasswordNotificationRequest) (*empty.Empty, error) {
|
||||||
err := s.user.RequestSetPassword(ctx, request.Id, notifyTypeToModel(request.Type))
|
err := s.command.RequestSetPassword(ctx, request.Id, notifyTypeToDomain(request.Type))
|
||||||
return &empty.Empty{}, err
|
return &empty.Empty{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) SetInitialPassword(ctx context.Context, request *management.PasswordRequest) (*empty.Empty, error) {
|
func (s *Server) SetInitialPassword(ctx context.Context, request *management.PasswordRequest) (*empty.Empty, error) {
|
||||||
_, err := s.user.SetOneTimePassword(ctx, passwordRequestToModel(request))
|
return &empty.Empty{}, s.command.SetOneTimePassword(ctx, authz.GetCtxData(ctx).OrgID, request.Id, request.Password)
|
||||||
return &empty.Empty{}, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) ResendInitialMail(ctx context.Context, request *management.InitialMailRequest) (*empty.Empty, error) {
|
func (s *Server) ResendInitialMail(ctx context.Context, request *management.InitialMailRequest) (*empty.Empty, error) {
|
||||||
err := s.user.ResendInitialMail(ctx, request.Id, request.Email)
|
return &empty.Empty{}, s.command.ResendInitialMail(ctx, request.Id, request.Email)
|
||||||
return &empty.Empty{}, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) SearchUserExternalIDPs(ctx context.Context, request *management.ExternalIDPSearchRequest) (*management.ExternalIDPSearchResponse, error) {
|
func (s *Server) SearchUserExternalIDPs(ctx context.Context, request *management.ExternalIDPSearchRequest) (*management.ExternalIDPSearchResponse, error) {
|
||||||
@ -211,8 +209,7 @@ func (s *Server) SearchUserExternalIDPs(ctx context.Context, request *management
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) RemoveExternalIDP(ctx context.Context, request *management.ExternalIDPRemoveRequest) (*empty.Empty, error) {
|
func (s *Server) RemoveExternalIDP(ctx context.Context, request *management.ExternalIDPRemoveRequest) (*empty.Empty, error) {
|
||||||
err := s.user.RemoveExternalIDP(ctx, externalIDPRemoveToModel(request))
|
return &empty.Empty{}, s.command.RemoveHumanExternalIDP(ctx, externalIDPRemoveToDomain(request))
|
||||||
return &empty.Empty{}, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) GetUserMfas(ctx context.Context, userID *management.UserID) (*management.UserMultiFactors, error) {
|
func (s *Server) GetUserMfas(ctx context.Context, userID *management.UserID) (*management.UserMultiFactors, error) {
|
||||||
@ -224,13 +221,11 @@ func (s *Server) GetUserMfas(ctx context.Context, userID *management.UserID) (*m
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) RemoveMfaOTP(ctx context.Context, userID *management.UserID) (*empty.Empty, error) {
|
func (s *Server) RemoveMfaOTP(ctx context.Context, userID *management.UserID) (*empty.Empty, error) {
|
||||||
err := s.user.RemoveOTP(ctx, userID.Id)
|
return &empty.Empty{}, s.command.RemoveHumanOTP(ctx, userID.Id)
|
||||||
return &empty.Empty{}, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) RemoveMfaU2F(ctx context.Context, webAuthNTokenID *management.WebAuthNTokenID) (*empty.Empty, error) {
|
func (s *Server) RemoveMfaU2F(ctx context.Context, webAuthNTokenID *management.WebAuthNTokenID) (*empty.Empty, error) {
|
||||||
err := s.user.RemoveU2F(ctx, webAuthNTokenID.UserId, webAuthNTokenID.Id)
|
return &empty.Empty{}, s.command.RemoveHumanU2F(ctx, webAuthNTokenID.UserId, webAuthNTokenID.Id)
|
||||||
return &empty.Empty{}, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) GetPasswordless(ctx context.Context, userID *management.UserID) (_ *management.WebAuthNTokens, err error) {
|
func (s *Server) GetPasswordless(ctx context.Context, userID *management.UserID) (_ *management.WebAuthNTokens, err error) {
|
||||||
@ -242,8 +237,7 @@ func (s *Server) GetPasswordless(ctx context.Context, userID *management.UserID)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) RemovePasswordless(ctx context.Context, id *management.WebAuthNTokenID) (*empty.Empty, error) {
|
func (s *Server) RemovePasswordless(ctx context.Context, id *management.WebAuthNTokenID) (*empty.Empty, error) {
|
||||||
err := s.user.RemovePasswordless(ctx, id.UserId, id.Id)
|
return &empty.Empty{}, s.command.RemoveHumanPasswordless(ctx, id.UserId, id.Id)
|
||||||
return &empty.Empty{}, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) SearchUserMemberships(ctx context.Context, in *management.UserMembershipSearchRequest) (*management.UserMembershipSearchResponse, error) {
|
func (s *Server) SearchUserMemberships(ctx context.Context, in *management.UserMembershipSearchRequest) (*management.UserMembershipSearchResponse, error) {
|
||||||
|
@ -76,11 +76,11 @@ func externalIDPSearchRequestToModel(request *management.ExternalIDPSearchReques
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func externalIDPRemoveToModel(idp *management.ExternalIDPRemoveRequest) *usr_model.ExternalIDP {
|
func externalIDPRemoveToDomain(idp *management.ExternalIDPRemoveRequest) *domain.ExternalIDP {
|
||||||
return &usr_model.ExternalIDP{
|
return &domain.ExternalIDP{
|
||||||
ObjectRoot: models.ObjectRoot{AggregateID: idp.UserId},
|
ObjectRoot: models.ObjectRoot{AggregateID: idp.UserId},
|
||||||
IDPConfigID: idp.IdpConfigId,
|
IDPConfigID: idp.IdpConfigId,
|
||||||
UserID: idp.ExternalUserId,
|
ExternalUserID: idp.ExternalUserId,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,7 +306,7 @@ func updateEmailToDomain(e *management.UpdateUserEmailRequest) *domain.Email {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func phoneFromModel(phone *usr_model.Phone) *management.UserPhone {
|
func phoneFromDomain(phone *domain.Phone) *management.UserPhone {
|
||||||
creationDate, err := ptypes.TimestampProto(phone.CreationDate)
|
creationDate, err := ptypes.TimestampProto(phone.CreationDate)
|
||||||
logging.Log("GRPC-ps9ws").OnError(err).Debug("unable to parse timestamp")
|
logging.Log("GRPC-ps9ws").OnError(err).Debug("unable to parse timestamp")
|
||||||
|
|
||||||
@ -339,8 +339,8 @@ func phoneViewFromModel(phone *usr_model.Phone) *management.UserPhoneView {
|
|||||||
IsPhoneVerified: phone.IsPhoneVerified,
|
IsPhoneVerified: phone.IsPhoneVerified,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func updatePhoneToModel(e *management.UpdateUserPhoneRequest) *usr_model.Phone {
|
func updatePhoneToDomain(e *management.UpdateUserPhoneRequest) *domain.Phone {
|
||||||
return &usr_model.Phone{
|
return &domain.Phone{
|
||||||
ObjectRoot: models.ObjectRoot{AggregateID: e.Id},
|
ObjectRoot: models.ObjectRoot{AggregateID: e.Id},
|
||||||
PhoneNumber: e.Phone,
|
PhoneNumber: e.Phone,
|
||||||
IsPhoneVerified: e.IsPhoneVerified,
|
IsPhoneVerified: e.IsPhoneVerified,
|
||||||
@ -510,14 +510,14 @@ func mfaFromModel(mfa *usr_model.MultiFactor) *management.UserMultiFactor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func notifyTypeToModel(state management.NotificationType) usr_model.NotificationType {
|
func notifyTypeToDomain(state management.NotificationType) domain.NotificationType {
|
||||||
switch state {
|
switch state {
|
||||||
case management.NotificationType_NOTIFICATIONTYPE_EMAIL:
|
case management.NotificationType_NOTIFICATIONTYPE_EMAIL:
|
||||||
return usr_model.NotificationTypeEmail
|
return domain.NotificationTypeEmail
|
||||||
case management.NotificationType_NOTIFICATIONTYPE_SMS:
|
case management.NotificationType_NOTIFICATIONTYPE_SMS:
|
||||||
return usr_model.NotificationTypeSms
|
return domain.NotificationTypeSms
|
||||||
default:
|
default:
|
||||||
return usr_model.NotificationTypeEmail
|
return domain.NotificationTypeEmail
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,13 +100,6 @@ func (repo *UserRepo) MyProfile(ctx context.Context) (*model.Profile, error) {
|
|||||||
return user.GetProfile()
|
return user.GetProfile()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *UserRepo) ChangeMyProfile(ctx context.Context, profile *model.Profile) (*model.Profile, error) {
|
|
||||||
if err := checkIDs(ctx, profile.ObjectRoot); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return repo.UserEvents.ChangeProfile(ctx, profile)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (repo *UserRepo) SearchMyExternalIDPs(ctx context.Context, request *model.ExternalIDPSearchRequest) (*model.ExternalIDPSearchResponse, error) {
|
func (repo *UserRepo) SearchMyExternalIDPs(ctx context.Context, request *model.ExternalIDPSearchRequest) (*model.ExternalIDPSearchResponse, error) {
|
||||||
request.EnsureLimit(repo.SearchLimit)
|
request.EnsureLimit(repo.SearchLimit)
|
||||||
sequence, seqErr := repo.View.GetLatestExternalIDPSequence("")
|
sequence, seqErr := repo.View.GetLatestExternalIDPSequence("")
|
||||||
@ -154,13 +147,6 @@ func (repo *UserRepo) MyEmail(ctx context.Context) (*model.Email, error) {
|
|||||||
return user.GetEmail()
|
return user.GetEmail()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *UserRepo) ChangeMyEmail(ctx context.Context, email *model.Email) (*model.Email, error) {
|
|
||||||
if err := checkIDs(ctx, email.ObjectRoot); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return repo.UserEvents.ChangeEmail(ctx, email)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (repo *UserRepo) VerifyEmail(ctx context.Context, userID, code string) error {
|
func (repo *UserRepo) VerifyEmail(ctx context.Context, userID, code string) error {
|
||||||
return repo.UserEvents.VerifyEmail(ctx, userID, code)
|
return repo.UserEvents.VerifyEmail(ctx, userID, code)
|
||||||
}
|
}
|
||||||
@ -388,18 +374,6 @@ func (repo *UserRepo) RemoveMyPasswordless(ctx context.Context, webAuthNTokenID
|
|||||||
return repo.UserEvents.RemovePasswordlessToken(ctx, authz.GetCtxData(ctx).UserID, webAuthNTokenID)
|
return repo.UserEvents.RemovePasswordlessToken(ctx, authz.GetCtxData(ctx).UserID, webAuthNTokenID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *UserRepo) ChangeMyUsername(ctx context.Context, username string) error {
|
|
||||||
ctxData := authz.GetCtxData(ctx)
|
|
||||||
orgPolicy, err := repo.View.OrgIAMPolicyByAggregateID(ctxData.OrgID)
|
|
||||||
if errors.IsNotFound(err) {
|
|
||||||
orgPolicy, err = repo.View.OrgIAMPolicyByAggregateID(repo.SystemDefaults.IamID)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
orgPolicyView := iam_es_model.OrgIAMViewToModel(orgPolicy)
|
|
||||||
return repo.UserEvents.ChangeUsername(ctx, ctxData.UserID, username, orgPolicyView)
|
|
||||||
}
|
|
||||||
func (repo *UserRepo) ResendInitVerificationMail(ctx context.Context, userID string) error {
|
func (repo *UserRepo) ResendInitVerificationMail(ctx context.Context, userID string) error {
|
||||||
_, err := repo.UserEvents.CreateInitializeUserCodeByID(ctx, userID)
|
_, err := repo.UserEvents.CreateInitializeUserCodeByID(ctx, userID)
|
||||||
return err
|
return err
|
||||||
|
@ -50,10 +50,8 @@ type myUserRepo interface {
|
|||||||
MyUser(ctx context.Context) (*model.UserView, error)
|
MyUser(ctx context.Context) (*model.UserView, error)
|
||||||
|
|
||||||
MyProfile(ctx context.Context) (*model.Profile, error)
|
MyProfile(ctx context.Context) (*model.Profile, error)
|
||||||
ChangeMyProfile(ctx context.Context, profile *model.Profile) (*model.Profile, error)
|
|
||||||
|
|
||||||
MyEmail(ctx context.Context) (*model.Email, error)
|
MyEmail(ctx context.Context) (*model.Email, error)
|
||||||
ChangeMyEmail(ctx context.Context, email *model.Email) (*model.Email, error)
|
|
||||||
VerifyMyEmail(ctx context.Context, code string) error
|
VerifyMyEmail(ctx context.Context, code string) error
|
||||||
ResendMyEmailVerificationMail(ctx context.Context) error
|
ResendMyEmailVerificationMail(ctx context.Context) error
|
||||||
|
|
||||||
@ -86,7 +84,5 @@ type myUserRepo interface {
|
|||||||
VerifyMyPasswordlessSetup(ctx context.Context, tokenName string, data []byte) error
|
VerifyMyPasswordlessSetup(ctx context.Context, tokenName string, data []byte) error
|
||||||
RemoveMyPasswordless(ctx context.Context, webAuthNTokenID string) error
|
RemoveMyPasswordless(ctx context.Context, webAuthNTokenID string) error
|
||||||
|
|
||||||
ChangeMyUsername(ctx context.Context, username string) error
|
|
||||||
|
|
||||||
MyUserChanges(ctx context.Context, lastSequence uint64, limit uint64, sortAscending bool) (*model.UserChanges, error)
|
MyUserChanges(ctx context.Context, lastSequence uint64, limit uint64, sortAscending bool) (*model.UserChanges, error)
|
||||||
}
|
}
|
||||||
|
@ -9,8 +9,6 @@ import (
|
|||||||
"github.com/caos/zitadel/internal/errors"
|
"github.com/caos/zitadel/internal/errors"
|
||||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||||
es_int "github.com/caos/zitadel/internal/eventstore"
|
es_int "github.com/caos/zitadel/internal/eventstore"
|
||||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
|
||||||
es_sdk "github.com/caos/zitadel/internal/eventstore/sdk"
|
|
||||||
iam_es_model "github.com/caos/zitadel/internal/iam/repository/view/model"
|
iam_es_model "github.com/caos/zitadel/internal/iam/repository/view/model"
|
||||||
"github.com/caos/zitadel/internal/management/repository/eventsourcing/view"
|
"github.com/caos/zitadel/internal/management/repository/eventsourcing/view"
|
||||||
global_model "github.com/caos/zitadel/internal/model"
|
global_model "github.com/caos/zitadel/internal/model"
|
||||||
@ -60,100 +58,6 @@ func (repo *UserRepo) UserByID(ctx context.Context, id string) (*usr_model.UserV
|
|||||||
return model.UserToModel(&userCopy), nil
|
return model.UserToModel(&userCopy), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *UserRepo) CreateUser(ctx context.Context, user *usr_model.User) (*usr_model.User, error) {
|
|
||||||
pwPolicy, err := repo.View.PasswordComplexityPolicyByAggregateID(authz.GetCtxData(ctx).OrgID)
|
|
||||||
if err != nil && caos_errs.IsNotFound(err) {
|
|
||||||
pwPolicy, err = repo.View.PasswordComplexityPolicyByAggregateID(repo.SystemDefaults.IamID)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
pwPolicyView := iam_es_model.PasswordComplexityViewToModel(pwPolicy)
|
|
||||||
orgPolicy, err := repo.View.OrgIAMPolicyByAggregateID(authz.GetCtxData(ctx).OrgID)
|
|
||||||
if err != nil && errors.IsNotFound(err) {
|
|
||||||
orgPolicy, err = repo.View.OrgIAMPolicyByAggregateID(repo.SystemDefaults.IamID)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
orgPolicyView := iam_es_model.OrgIAMViewToModel(orgPolicy)
|
|
||||||
return repo.UserEvents.CreateUser(ctx, user, pwPolicyView, orgPolicyView)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (repo *UserRepo) RegisterUser(ctx context.Context, user *usr_model.User, resourceOwner string) (*usr_model.User, error) {
|
|
||||||
policyResourceOwner := authz.GetCtxData(ctx).OrgID
|
|
||||||
if resourceOwner != "" {
|
|
||||||
policyResourceOwner = resourceOwner
|
|
||||||
}
|
|
||||||
pwPolicy, err := repo.View.PasswordComplexityPolicyByAggregateID(policyResourceOwner)
|
|
||||||
if err != nil && caos_errs.IsNotFound(err) {
|
|
||||||
pwPolicy, err = repo.View.PasswordComplexityPolicyByAggregateID(repo.SystemDefaults.IamID)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
pwPolicyView := iam_es_model.PasswordComplexityViewToModel(pwPolicy)
|
|
||||||
orgPolicy, err := repo.View.OrgIAMPolicyByAggregateID(authz.GetCtxData(ctx).OrgID)
|
|
||||||
if err != nil && errors.IsNotFound(err) {
|
|
||||||
orgPolicy, err = repo.View.OrgIAMPolicyByAggregateID(repo.SystemDefaults.IamID)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
orgPolicyView := iam_es_model.OrgIAMViewToModel(orgPolicy)
|
|
||||||
return repo.UserEvents.RegisterUser(ctx, user, pwPolicyView, orgPolicyView, resourceOwner)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (repo *UserRepo) DeactivateUser(ctx context.Context, id string) (*usr_model.User, error) {
|
|
||||||
return repo.UserEvents.DeactivateUser(ctx, id)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (repo *UserRepo) ReactivateUser(ctx context.Context, id string) (*usr_model.User, error) {
|
|
||||||
return repo.UserEvents.ReactivateUser(ctx, id)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (repo *UserRepo) LockUser(ctx context.Context, id string) (*usr_model.User, error) {
|
|
||||||
return repo.UserEvents.LockUser(ctx, id)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (repo *UserRepo) UnlockUser(ctx context.Context, id string) (*usr_model.User, error) {
|
|
||||||
return repo.UserEvents.UnlockUser(ctx, id)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (repo *UserRepo) RemoveUser(ctx context.Context, id string) error {
|
|
||||||
aggregates := make([]*es_models.Aggregate, 0)
|
|
||||||
orgPolicy, err := repo.View.OrgIAMPolicyByAggregateID(authz.GetCtxData(ctx).OrgID)
|
|
||||||
if err != nil && errors.IsNotFound(err) {
|
|
||||||
orgPolicy, err = repo.View.OrgIAMPolicyByAggregateID(repo.SystemDefaults.IamID)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
orgPolicyView := iam_es_model.OrgIAMViewToModel(orgPolicy)
|
|
||||||
user, agg, err := repo.UserEvents.PrepareRemoveUser(ctx, id, orgPolicyView)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
aggregates = append(aggregates, agg...)
|
|
||||||
|
|
||||||
// remove user_grants
|
|
||||||
usergrants, err := repo.View.UserGrantsByUserID(id)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for _, grant := range usergrants {
|
|
||||||
_, aggs, err := repo.UserGrantEvents.PrepareRemoveUserGrant(ctx, grant.ID, true)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for _, agg := range aggs {
|
|
||||||
aggregates = append(aggregates, agg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return es_sdk.PushAggregates(ctx, repo.Eventstore.PushAggregates, user.AppendEvents, aggregates...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (repo *UserRepo) SearchUsers(ctx context.Context, request *usr_model.UserSearchRequest) (*usr_model.UserSearchResponse, error) {
|
func (repo *UserRepo) SearchUsers(ctx context.Context, request *usr_model.UserSearchRequest) (*usr_model.UserSearchResponse, error) {
|
||||||
request.EnsureLimit(repo.SearchLimit)
|
request.EnsureLimit(repo.SearchLimit)
|
||||||
sequence, sequenceErr := repo.View.GetLatestUserSequence("")
|
sequence, sequenceErr := repo.View.GetLatestUserSequence("")
|
||||||
@ -225,42 +129,10 @@ func (repo *UserRepo) UserMFAs(ctx context.Context, userID string) ([]*usr_model
|
|||||||
return mfas, nil
|
return mfas, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *UserRepo) RemoveOTP(ctx context.Context, userID string) error {
|
|
||||||
return repo.UserEvents.RemoveOTP(ctx, userID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (repo *UserRepo) RemoveU2F(ctx context.Context, userID, webAuthNTokenID string) error {
|
|
||||||
return repo.UserEvents.RemoveU2FToken(ctx, userID, webAuthNTokenID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (repo *UserRepo) GetPasswordless(ctx context.Context, userID string) ([]*usr_model.WebAuthNToken, error) {
|
func (repo *UserRepo) GetPasswordless(ctx context.Context, userID string) ([]*usr_model.WebAuthNToken, error) {
|
||||||
return repo.UserEvents.GetPasswordless(ctx, userID)
|
return repo.UserEvents.GetPasswordless(ctx, userID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *UserRepo) RemovePasswordless(ctx context.Context, userID, webAuthNTokenID string) error {
|
|
||||||
return repo.UserEvents.RemovePasswordlessToken(ctx, userID, webAuthNTokenID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (repo *UserRepo) SetOneTimePassword(ctx context.Context, password *usr_model.Password) (*usr_model.Password, error) {
|
|
||||||
policy, err := repo.View.PasswordComplexityPolicyByAggregateID(authz.GetCtxData(ctx).OrgID)
|
|
||||||
if err != nil && caos_errs.IsNotFound(err) {
|
|
||||||
policy, err = repo.View.PasswordComplexityPolicyByAggregateID(repo.SystemDefaults.IamID)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
pwPolicyView := iam_es_model.PasswordComplexityViewToModel(policy)
|
|
||||||
return repo.UserEvents.SetOneTimePassword(ctx, pwPolicyView, password)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (repo *UserRepo) RequestSetPassword(ctx context.Context, id string, notifyType usr_model.NotificationType) error {
|
|
||||||
return repo.UserEvents.RequestSetPassword(ctx, id, notifyType)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (repo *UserRepo) ResendInitialMail(ctx context.Context, userID, email string) error {
|
|
||||||
return repo.UserEvents.ResendInitialMail(ctx, userID, email)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (repo *UserRepo) ProfileByID(ctx context.Context, userID string) (*usr_model.Profile, error) {
|
func (repo *UserRepo) ProfileByID(ctx context.Context, userID string) (*usr_model.Profile, error) {
|
||||||
user, err := repo.UserByID(ctx, userID)
|
user, err := repo.UserByID(ctx, userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -293,14 +165,6 @@ func (repo *UserRepo) SearchExternalIDPs(ctx context.Context, request *usr_model
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *UserRepo) RemoveExternalIDP(ctx context.Context, externalIDP *usr_model.ExternalIDP) error {
|
|
||||||
return repo.UserEvents.RemoveExternalIDP(ctx, externalIDP)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (repo *UserRepo) ChangeMachine(ctx context.Context, machine *usr_model.Machine) (*usr_model.Machine, error) {
|
|
||||||
return repo.UserEvents.ChangeMachine(ctx, machine)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (repo *UserRepo) GetMachineKey(ctx context.Context, userID, keyID string) (*usr_model.MachineKeyView, error) {
|
func (repo *UserRepo) GetMachineKey(ctx context.Context, userID, keyID string) (*usr_model.MachineKeyView, error) {
|
||||||
key, err := repo.View.MachineKeyByIDs(userID, keyID)
|
key, err := repo.View.MachineKeyByIDs(userID, keyID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -338,10 +202,6 @@ func (repo *UserRepo) RemoveMachineKey(ctx context.Context, userID, keyID string
|
|||||||
return repo.UserEvents.RemoveMachineKey(ctx, userID, keyID)
|
return repo.UserEvents.RemoveMachineKey(ctx, userID, keyID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *UserRepo) ChangeProfile(ctx context.Context, profile *usr_model.Profile) (*usr_model.Profile, error) {
|
|
||||||
return repo.UserEvents.ChangeProfile(ctx, profile)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (repo *UserRepo) ChangeUsername(ctx context.Context, userID, userName string) error {
|
func (repo *UserRepo) ChangeUsername(ctx context.Context, userID, userName string) error {
|
||||||
orgPolicy, err := repo.View.OrgIAMPolicyByAggregateID(authz.GetCtxData(ctx).OrgID)
|
orgPolicy, err := repo.View.OrgIAMPolicyByAggregateID(authz.GetCtxData(ctx).OrgID)
|
||||||
if err != nil && errors.IsNotFound(err) {
|
if err != nil && errors.IsNotFound(err) {
|
||||||
@ -365,14 +225,6 @@ func (repo *UserRepo) EmailByID(ctx context.Context, userID string) (*usr_model.
|
|||||||
return user.GetEmail()
|
return user.GetEmail()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *UserRepo) ChangeEmail(ctx context.Context, email *usr_model.Email) (*usr_model.Email, error) {
|
|
||||||
return repo.UserEvents.ChangeEmail(ctx, email)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (repo *UserRepo) CreateEmailVerificationCode(ctx context.Context, userID string) error {
|
|
||||||
return repo.UserEvents.CreateEmailVerificationCode(ctx, userID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (repo *UserRepo) PhoneByID(ctx context.Context, userID string) (*usr_model.Phone, error) {
|
func (repo *UserRepo) PhoneByID(ctx context.Context, userID string) (*usr_model.Phone, error) {
|
||||||
user, err := repo.UserByID(ctx, userID)
|
user, err := repo.UserByID(ctx, userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -384,18 +236,6 @@ func (repo *UserRepo) PhoneByID(ctx context.Context, userID string) (*usr_model.
|
|||||||
return user.GetPhone()
|
return user.GetPhone()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *UserRepo) ChangePhone(ctx context.Context, email *usr_model.Phone) (*usr_model.Phone, error) {
|
|
||||||
return repo.UserEvents.ChangePhone(ctx, email)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (repo *UserRepo) RemovePhone(ctx context.Context, userID string) error {
|
|
||||||
return repo.UserEvents.RemovePhone(ctx, userID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (repo *UserRepo) CreatePhoneVerificationCode(ctx context.Context, userID string) error {
|
|
||||||
return repo.UserEvents.CreatePhoneVerificationCode(ctx, userID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (repo *UserRepo) AddressByID(ctx context.Context, userID string) (*usr_model.Address, error) {
|
func (repo *UserRepo) AddressByID(ctx context.Context, userID string) (*usr_model.Address, error) {
|
||||||
user, err := repo.UserByID(ctx, userID)
|
user, err := repo.UserByID(ctx, userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -407,10 +247,6 @@ func (repo *UserRepo) AddressByID(ctx context.Context, userID string) (*usr_mode
|
|||||||
return user.GetAddress()
|
return user.GetAddress()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *UserRepo) ChangeAddress(ctx context.Context, address *usr_model.Address) (*usr_model.Address, error) {
|
|
||||||
return repo.UserEvents.ChangeAddress(ctx, address)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (repo *UserRepo) SearchUserMemberships(ctx context.Context, request *usr_model.UserMembershipSearchRequest) (*usr_model.UserMembershipSearchResponse, error) {
|
func (repo *UserRepo) SearchUserMemberships(ctx context.Context, request *usr_model.UserMembershipSearchRequest) (*usr_model.UserMembershipSearchResponse, error) {
|
||||||
request.EnsureLimit(repo.SearchLimit)
|
request.EnsureLimit(repo.SearchLimit)
|
||||||
sequence, sequenceErr := repo.View.GetLatestUserMembershipSequence("")
|
sequence, sequenceErr := repo.View.GetLatestUserMembershipSequence("")
|
||||||
|
@ -8,13 +8,6 @@ import (
|
|||||||
|
|
||||||
type UserRepository interface {
|
type UserRepository interface {
|
||||||
UserByID(ctx context.Context, id string) (*model.UserView, error)
|
UserByID(ctx context.Context, id string) (*model.UserView, error)
|
||||||
CreateUser(ctx context.Context, user *model.User) (*model.User, error)
|
|
||||||
RegisterUser(ctx context.Context, user *model.User, resourceOwner string) (*model.User, error)
|
|
||||||
DeactivateUser(ctx context.Context, id string) (*model.User, error)
|
|
||||||
ReactivateUser(ctx context.Context, id string) (*model.User, error)
|
|
||||||
LockUser(ctx context.Context, id string) (*model.User, error)
|
|
||||||
UnlockUser(ctx context.Context, id string) (*model.User, error)
|
|
||||||
RemoveUser(ctx context.Context, id string) error
|
|
||||||
SearchUsers(ctx context.Context, request *model.UserSearchRequest) (*model.UserSearchResponse, error)
|
SearchUsers(ctx context.Context, request *model.UserSearchRequest) (*model.UserSearchResponse, error)
|
||||||
|
|
||||||
GetUserByLoginNameGlobal(ctx context.Context, email string) (*model.UserView, error)
|
GetUserByLoginNameGlobal(ctx context.Context, email string) (*model.UserView, error)
|
||||||
@ -22,43 +15,24 @@ type UserRepository interface {
|
|||||||
|
|
||||||
UserChanges(ctx context.Context, id string, lastSequence uint64, limit uint64, sortAscending bool) (*model.UserChanges, error)
|
UserChanges(ctx context.Context, id string, lastSequence uint64, limit uint64, sortAscending bool) (*model.UserChanges, error)
|
||||||
|
|
||||||
ChangeUsername(ctx context.Context, id, username string) error
|
|
||||||
|
|
||||||
SetOneTimePassword(ctx context.Context, password *model.Password) (*model.Password, error)
|
|
||||||
RequestSetPassword(ctx context.Context, id string, notifyType model.NotificationType) error
|
|
||||||
|
|
||||||
ProfileByID(ctx context.Context, userID string) (*model.Profile, error)
|
ProfileByID(ctx context.Context, userID string) (*model.Profile, error)
|
||||||
ChangeProfile(ctx context.Context, profile *model.Profile) (*model.Profile, error)
|
|
||||||
|
|
||||||
UserMFAs(ctx context.Context, userID string) ([]*model.MultiFactor, error)
|
UserMFAs(ctx context.Context, userID string) ([]*model.MultiFactor, error)
|
||||||
RemoveOTP(ctx context.Context, userID string) error
|
|
||||||
RemoveU2F(ctx context.Context, userID, webAuthNTokenID string) error
|
|
||||||
|
|
||||||
GetPasswordless(ctx context.Context, userID string) ([]*model.WebAuthNToken, error)
|
GetPasswordless(ctx context.Context, userID string) ([]*model.WebAuthNToken, error)
|
||||||
RemovePasswordless(ctx context.Context, userID, webAuthNTokenID string) error
|
|
||||||
|
|
||||||
SearchExternalIDPs(ctx context.Context, request *model.ExternalIDPSearchRequest) (*model.ExternalIDPSearchResponse, error)
|
SearchExternalIDPs(ctx context.Context, request *model.ExternalIDPSearchRequest) (*model.ExternalIDPSearchResponse, error)
|
||||||
RemoveExternalIDP(ctx context.Context, externalIDP *model.ExternalIDP) error
|
|
||||||
|
|
||||||
SearchMachineKeys(ctx context.Context, request *model.MachineKeySearchRequest) (*model.MachineKeySearchResponse, error)
|
SearchMachineKeys(ctx context.Context, request *model.MachineKeySearchRequest) (*model.MachineKeySearchResponse, error)
|
||||||
GetMachineKey(ctx context.Context, userID, keyID string) (*model.MachineKeyView, error)
|
GetMachineKey(ctx context.Context, userID, keyID string) (*model.MachineKeyView, error)
|
||||||
ChangeMachine(ctx context.Context, machine *model.Machine) (*model.Machine, error)
|
|
||||||
AddMachineKey(ctx context.Context, key *model.MachineKey) (*model.MachineKey, error)
|
AddMachineKey(ctx context.Context, key *model.MachineKey) (*model.MachineKey, error)
|
||||||
RemoveMachineKey(ctx context.Context, userID, keyID string) error
|
RemoveMachineKey(ctx context.Context, userID, keyID string) error
|
||||||
|
|
||||||
EmailByID(ctx context.Context, userID string) (*model.Email, error)
|
EmailByID(ctx context.Context, userID string) (*model.Email, error)
|
||||||
ChangeEmail(ctx context.Context, email *model.Email) (*model.Email, error)
|
|
||||||
CreateEmailVerificationCode(ctx context.Context, userID string) error
|
|
||||||
|
|
||||||
PhoneByID(ctx context.Context, userID string) (*model.Phone, error)
|
PhoneByID(ctx context.Context, userID string) (*model.Phone, error)
|
||||||
ChangePhone(ctx context.Context, email *model.Phone) (*model.Phone, error)
|
|
||||||
RemovePhone(ctx context.Context, userID string) error
|
|
||||||
CreatePhoneVerificationCode(ctx context.Context, userID string) error
|
|
||||||
|
|
||||||
AddressByID(ctx context.Context, userID string) (*model.Address, error)
|
AddressByID(ctx context.Context, userID string) (*model.Address, error)
|
||||||
ChangeAddress(ctx context.Context, address *model.Address) (*model.Address, error)
|
|
||||||
|
|
||||||
SearchUserMemberships(ctx context.Context, request *model.UserMembershipSearchRequest) (*model.UserMembershipSearchResponse, error)
|
SearchUserMemberships(ctx context.Context, request *model.UserMembershipSearchRequest) (*model.UserMembershipSearchResponse, error)
|
||||||
|
|
||||||
ResendInitialMail(ctx context.Context, userID, email string) error
|
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ Errors:
|
|||||||
Internal: Es ist ein interner Fehler aufgetreten
|
Internal: Es ist ein interner Fehler aufgetreten
|
||||||
NoChangesFound: Keine Änderungen gefunden
|
NoChangesFound: Keine Änderungen gefunden
|
||||||
OriginNotAllowed: Dieser "Origin" ist nicht freigeschaltet
|
OriginNotAllowed: Dieser "Origin" ist nicht freigeschaltet
|
||||||
|
IDMissing: ID fehlt
|
||||||
User:
|
User:
|
||||||
NotFound: Benutzer konnte nicht gefunden werden
|
NotFound: Benutzer konnte nicht gefunden werden
|
||||||
NotFoundOnOrg: Benutzer konnte in der gewünschten Organisation nicht gefunden werden
|
NotFoundOnOrg: Benutzer konnte in der gewünschten Organisation nicht gefunden werden
|
||||||
@ -19,6 +20,7 @@ Errors:
|
|||||||
NotLocked: Benutzer ist nicht gesperrt
|
NotLocked: Benutzer ist nicht gesperrt
|
||||||
NoChanges: Keine Änderungen gefunden
|
NoChanges: Keine Änderungen gefunden
|
||||||
InitCodeNotFound: Kein Initialisierungs Code gefunden
|
InitCodeNotFound: Kein Initialisierungs Code gefunden
|
||||||
|
UsernameNotChanged: Benutzername wurde nicht verändert
|
||||||
Profile:
|
Profile:
|
||||||
NotFound: Profil nicht gefunden
|
NotFound: Profil nicht gefunden
|
||||||
NotChanged: Profile nicht verändert
|
NotChanged: Profile nicht verändert
|
||||||
|
@ -2,6 +2,7 @@ Errors:
|
|||||||
Internal: An internal error occured
|
Internal: An internal error occured
|
||||||
NoChangesFound: No changes
|
NoChangesFound: No changes
|
||||||
OriginNotAllowed: This "Origin" is not allowed
|
OriginNotAllowed: This "Origin" is not allowed
|
||||||
|
IDMissing: ID missing
|
||||||
User:
|
User:
|
||||||
NotFound: User could not be found
|
NotFound: User could not be found
|
||||||
NotFoundOnOrg: User could not be found on chosen organisation
|
NotFoundOnOrg: User could not be found on chosen organisation
|
||||||
@ -19,6 +20,7 @@ Errors:
|
|||||||
NotLocked: User is not locked
|
NotLocked: User is not locked
|
||||||
NoChanges: No changes found
|
NoChanges: No changes found
|
||||||
InitCodeNotFound: Initialization Code not found
|
InitCodeNotFound: Initialization Code not found
|
||||||
|
UsernameNotChanged: Username not changed
|
||||||
Profile:
|
Profile:
|
||||||
NotFound: Profile not found
|
NotFound: Profile not found
|
||||||
NotChanged: Profile not changed
|
NotChanged: Profile not changed
|
||||||
|
@ -63,12 +63,12 @@ func (r *CommandSide) ChangeDefaultIDPConfig(ctx context.Context, config *domain
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if existingIDP.State == domain.IDPConfigStateRemoved || existingIDP.State == domain.IDPConfigStateUnspecified {
|
if existingIDP.State == domain.IDPConfigStateRemoved || existingIDP.State == domain.IDPConfigStateUnspecified {
|
||||||
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-4M9so", "Errors.IAM.IDPConfig.NotExisting")
|
return nil, caos_errs.ThrowNotFound(nil, "IAM-4M9so", "Errors.IAM.IDPConfig.NotExisting")
|
||||||
}
|
}
|
||||||
|
|
||||||
changedEvent, hasChanged := existingIDP.NewChangedEvent(ctx, config.IDPConfigID, config.Name, config.StylingType)
|
changedEvent, hasChanged := existingIDP.NewChangedEvent(ctx, config.IDPConfigID, config.Name, config.StylingType)
|
||||||
if !hasChanged {
|
if !hasChanged {
|
||||||
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-4M9vs", "Errors.IAM.LabelPolicy.NotChanged")
|
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-4M9vs", "Errors.IAM.LabelPolicy.NotChanged")
|
||||||
}
|
}
|
||||||
iamAgg := IAMAggregateFromWriteModel(&existingIDP.WriteModel)
|
iamAgg := IAMAggregateFromWriteModel(&existingIDP.WriteModel)
|
||||||
iamAgg.PushEvents(changedEvent)
|
iamAgg.PushEvents(changedEvent)
|
||||||
@ -86,7 +86,7 @@ func (r *CommandSide) DeactivateDefaultIDPConfig(ctx context.Context, idpID stri
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if existingIDP.State != domain.IDPConfigStateActive {
|
if existingIDP.State != domain.IDPConfigStateActive {
|
||||||
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-4M9so", "Errors.IAM.IDPConfig.NotActive")
|
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-4M9so", "Errors.IAM.IDPConfig.NotActive")
|
||||||
}
|
}
|
||||||
iamAgg := IAMAggregateFromWriteModel(&existingIDP.WriteModel)
|
iamAgg := IAMAggregateFromWriteModel(&existingIDP.WriteModel)
|
||||||
iamAgg.PushEvents(iam_repo.NewIDPConfigDeactivatedEvent(ctx, idpID))
|
iamAgg.PushEvents(iam_repo.NewIDPConfigDeactivatedEvent(ctx, idpID))
|
||||||
@ -104,7 +104,7 @@ func (r *CommandSide) ReactivateDefaultIDPConfig(ctx context.Context, idpID stri
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if existingIDP.State != domain.IDPConfigStateInactive {
|
if existingIDP.State != domain.IDPConfigStateInactive {
|
||||||
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-5Mo0d", "Errors.IAM.IDPConfig.NotInactive")
|
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-5Mo0d", "Errors.IAM.IDPConfig.NotInactive")
|
||||||
}
|
}
|
||||||
iamAgg := IAMAggregateFromWriteModel(&existingIDP.WriteModel)
|
iamAgg := IAMAggregateFromWriteModel(&existingIDP.WriteModel)
|
||||||
iamAgg.PushEvents(iam_repo.NewIDPConfigReactivatedEvent(ctx, idpID))
|
iamAgg.PushEvents(iam_repo.NewIDPConfigReactivatedEvent(ctx, idpID))
|
||||||
|
@ -30,7 +30,7 @@ func (r *CommandSide) ChangeDefaultIDPOIDCConfig(ctx context.Context, config *do
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if !hasChanged {
|
if !hasChanged {
|
||||||
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-4M9vs", "Errors.IAM.LabelPolicy.NotChanged")
|
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-4M9vs", "Errors.IAM.LabelPolicy.NotChanged")
|
||||||
}
|
}
|
||||||
|
|
||||||
iamAgg := IAMAggregateFromWriteModel(&existingConfig.WriteModel)
|
iamAgg := IAMAggregateFromWriteModel(&existingConfig.WriteModel)
|
||||||
|
@ -23,7 +23,7 @@ func (r *CommandSide) AddIAMMember(ctx context.Context, member *domain.IAMMember
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if addedMember.IsActive {
|
if addedMember.State == domain.MemberStateActive {
|
||||||
return nil, errors.ThrowAlreadyExists(nil, "IAM-PtXi1", "Errors.IAM.Member.AlreadyExists")
|
return nil, errors.ThrowAlreadyExists(nil, "IAM-PtXi1", "Errors.IAM.Member.AlreadyExists")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,7 +95,7 @@ func (r *CommandSide) iamMemberWriteModelByID(ctx context.Context, iamID, userID
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !writeModel.IsActive {
|
if writeModel.State == domain.MemberStateUnspecified || writeModel.State == domain.MemberStateRemoved {
|
||||||
return nil, errors.ThrowNotFound(nil, "IAM-D8JxR", "Errors.NotFound")
|
return nil, errors.ThrowNotFound(nil, "IAM-D8JxR", "Errors.NotFound")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ func (r *CommandSide) addDefaultLabelPolicy(ctx context.Context, iamAgg *iam_rep
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if addedPolicy.IsActive {
|
if addedPolicy.State == domain.PolicyStateActive {
|
||||||
return caos_errs.ThrowAlreadyExists(nil, "IAM-2B0ps", "Errors.IAM.LabelPolicy.AlreadyExists")
|
return caos_errs.ThrowAlreadyExists(nil, "IAM-2B0ps", "Errors.IAM.LabelPolicy.AlreadyExists")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,13 +46,13 @@ func (r *CommandSide) ChangeDefaultLabelPolicy(ctx context.Context, policy *doma
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !existingPolicy.IsActive {
|
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||||
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-0K9dq", "Errors.IAM.LabelPolicy.NotFound")
|
return nil, caos_errs.ThrowNotFound(nil, "IAM-0K9dq", "Errors.IAM.LabelPolicy.NotFound")
|
||||||
}
|
}
|
||||||
|
|
||||||
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, policy.PrimaryColor, policy.SecondaryColor)
|
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, policy.PrimaryColor, policy.SecondaryColor)
|
||||||
if !hasChanged {
|
if !hasChanged {
|
||||||
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-4M9vs", "Errors.IAM.LabelPolicy.NotChanged")
|
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-4M9vs", "Errors.IAM.LabelPolicy.NotChanged")
|
||||||
}
|
}
|
||||||
|
|
||||||
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.LabelPolicyWriteModel.WriteModel)
|
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.LabelPolicyWriteModel.WriteModel)
|
||||||
|
@ -42,7 +42,7 @@ func (r *CommandSide) addDefaultLoginPolicy(ctx context.Context, iamAgg *iam_rep
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if addedPolicy.IsActive {
|
if addedPolicy.State == domain.PolicyStateActive {
|
||||||
return caos_errs.ThrowAlreadyExists(nil, "IAM-2B0ps", "Errors.IAM.LoginPolicy.AlreadyExists")
|
return caos_errs.ThrowAlreadyExists(nil, "IAM-2B0ps", "Errors.IAM.LoginPolicy.AlreadyExists")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,12 +73,12 @@ func (r *CommandSide) changeDefaultLoginPolicy(ctx context.Context, iamAgg *iam_
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !existingPolicy.IsActive {
|
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||||
return caos_errs.ThrowAlreadyExists(nil, "IAM-M0sif", "Errors.IAM.LoginPolicy.NotFound")
|
return caos_errs.ThrowNotFound(nil, "IAM-M0sif", "Errors.IAM.LoginPolicy.NotFound")
|
||||||
}
|
}
|
||||||
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, policy.AllowUsernamePassword, policy.AllowRegister, policy.AllowExternalIdp, policy.ForceMFA, domain.PasswordlessType(policy.PasswordlessType))
|
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, policy.AllowUsernamePassword, policy.AllowRegister, policy.AllowExternalIdp, policy.ForceMFA, domain.PasswordlessType(policy.PasswordlessType))
|
||||||
if !hasChanged {
|
if !hasChanged {
|
||||||
return caos_errs.ThrowAlreadyExists(nil, "IAM-5M9vdd", "Errors.IAM.LoginPolicy.NotChanged")
|
return caos_errs.ThrowPreconditionFailed(nil, "IAM-5M9vdd", "Errors.IAM.LoginPolicy.NotChanged")
|
||||||
}
|
}
|
||||||
iamAgg.PushEvents(changedEvent)
|
iamAgg.PushEvents(changedEvent)
|
||||||
|
|
||||||
@ -92,7 +92,7 @@ func (r *CommandSide) AddIDPProviderToDefaultLoginPolicy(ctx context.Context, id
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if idpModel.IsActive {
|
if idpModel.State == domain.IdentityProviderStateActive {
|
||||||
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-2B0ps", "Errors.IAM.LoginPolicy.IDP.AlreadyExists")
|
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-2B0ps", "Errors.IAM.LoginPolicy.IDP.AlreadyExists")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,8 +113,8 @@ func (r *CommandSide) RemoveIDPProviderFromDefaultLoginPolicy(ctx context.Contex
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !idpModel.IsActive {
|
if idpModel.State == domain.IdentityProviderStateUnspecified || idpModel.State == domain.IdentityProviderStateRemoved {
|
||||||
return caos_errs.ThrowAlreadyExists(nil, "IAM-39fjs", "Errors.IAM.LoginPolicy.IDP.NotExisting")
|
return caos_errs.ThrowNotFound(nil, "IAM-39fjs", "Errors.IAM.LoginPolicy.IDP.NotExisting")
|
||||||
}
|
}
|
||||||
iamAgg := IAMAggregateFromWriteModel(&idpModel.IdentityProviderWriteModel.WriteModel)
|
iamAgg := IAMAggregateFromWriteModel(&idpModel.IdentityProviderWriteModel.WriteModel)
|
||||||
iamAgg.PushEvents(iam_repo.NewIdentityProviderRemovedEvent(ctx, idpProvider.IDPConfigID))
|
iamAgg.PushEvents(iam_repo.NewIdentityProviderRemovedEvent(ctx, idpProvider.IDPConfigID))
|
||||||
@ -143,7 +143,7 @@ func (r *CommandSide) addSecondFactorToDefaultLoginPolicy(ctx context.Context, i
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if secondFactorModel.IsActive {
|
if secondFactorModel.State == domain.FactorStateActive {
|
||||||
return caos_errs.ThrowAlreadyExists(nil, "IAM-2B0ps", "Errors.IAM.LoginPolicy.MFA.AlreadyExists")
|
return caos_errs.ThrowAlreadyExists(nil, "IAM-2B0ps", "Errors.IAM.LoginPolicy.MFA.AlreadyExists")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,8 +158,8 @@ func (r *CommandSide) RemoveSecondFactorFromDefaultLoginPolicy(ctx context.Conte
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !secondFactorModel.IsActive {
|
if secondFactorModel.State == domain.FactorStateUnspecified || secondFactorModel.State == domain.FactorStateRemoved {
|
||||||
return caos_errs.ThrowAlreadyExists(nil, "IAM-3M9od", "Errors.IAM.LoginPolicy.MFA.NotExisting")
|
return caos_errs.ThrowNotFound(nil, "IAM-3M9od", "Errors.IAM.LoginPolicy.MFA.NotExisting")
|
||||||
}
|
}
|
||||||
iamAgg := IAMAggregateFromWriteModel(&secondFactorModel.SecondFactorWriteModel.WriteModel)
|
iamAgg := IAMAggregateFromWriteModel(&secondFactorModel.SecondFactorWriteModel.WriteModel)
|
||||||
iamAgg.PushEvents(iam_repo.NewLoginPolicySecondFactorRemovedEvent(ctx, domain.SecondFactorType(secondFactor)))
|
iamAgg.PushEvents(iam_repo.NewLoginPolicySecondFactorRemovedEvent(ctx, domain.SecondFactorType(secondFactor)))
|
||||||
@ -187,7 +187,7 @@ func (r *CommandSide) addMultiFactorToDefaultLoginPolicy(ctx context.Context, ia
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if multiFactorModel.IsActive {
|
if multiFactorModel.State == domain.FactorStateActive {
|
||||||
return caos_errs.ThrowAlreadyExists(nil, "IAM-3M9od", "Errors.IAM.LoginPolicy.MFA.AlreadyExists")
|
return caos_errs.ThrowAlreadyExists(nil, "IAM-3M9od", "Errors.IAM.LoginPolicy.MFA.AlreadyExists")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,8 +202,8 @@ func (r *CommandSide) RemoveMultiFactorFromDefaultLoginPolicy(ctx context.Contex
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if multiFactorModel.IsActive {
|
if multiFactorModel.State == domain.FactorStateUnspecified || multiFactorModel.State == domain.FactorStateRemoved {
|
||||||
return caos_errs.ThrowAlreadyExists(nil, "IAM-3M9df", "Errors.IAM.LoginPolicy.MFA.NotExisting")
|
return caos_errs.ThrowNotFound(nil, "IAM-3M9df", "Errors.IAM.LoginPolicy.MFA.NotExisting")
|
||||||
}
|
}
|
||||||
iamAgg := IAMAggregateFromWriteModel(&multiFactorModel.MultiFactoryWriteModel.WriteModel)
|
iamAgg := IAMAggregateFromWriteModel(&multiFactorModel.MultiFactoryWriteModel.WriteModel)
|
||||||
iamAgg.PushEvents(iam_repo.NewLoginPolicyMultiFactorRemovedEvent(ctx, domain.MultiFactorType(multiFactor)))
|
iamAgg.PushEvents(iam_repo.NewLoginPolicyMultiFactorRemovedEvent(ctx, domain.MultiFactorType(multiFactor)))
|
||||||
|
@ -41,7 +41,7 @@ func (r *CommandSide) addDefaultOrgIAMPolicy(ctx context.Context, iamAgg *iam_re
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if addedPolicy.IsActive {
|
if addedPolicy.State == domain.PolicyStateActive {
|
||||||
return caos_errs.ThrowAlreadyExists(nil, "IAM-Lk0dS", "Errors.IAM.OrgIAMPolicy.AlreadyExists")
|
return caos_errs.ThrowAlreadyExists(nil, "IAM-Lk0dS", "Errors.IAM.OrgIAMPolicy.AlreadyExists")
|
||||||
}
|
}
|
||||||
iamAgg.PushEvents(iam_repo.NewOrgIAMPolicyAddedEvent(ctx, policy.UserLoginMustBeDomain))
|
iamAgg.PushEvents(iam_repo.NewOrgIAMPolicyAddedEvent(ctx, policy.UserLoginMustBeDomain))
|
||||||
@ -55,13 +55,13 @@ func (r *CommandSide) ChangeDefaultOrgIAMPolicy(ctx context.Context, policy *dom
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if !existingPolicy.IsActive {
|
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||||
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-0Pl0d", "Errors.IAM.OrgIAMPolicy.NotFound")
|
return nil, caos_errs.ThrowNotFound(nil, "IAM-0Pl0d", "Errors.IAM.OrgIAMPolicy.NotFound")
|
||||||
}
|
}
|
||||||
|
|
||||||
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, policy.UserLoginMustBeDomain)
|
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, policy.UserLoginMustBeDomain)
|
||||||
if !hasChanged {
|
if !hasChanged {
|
||||||
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-4M9vs", "Errors.IAM.LabelPolicy.NotChanged")
|
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-4M9vs", "Errors.IAM.LabelPolicy.NotChanged")
|
||||||
}
|
}
|
||||||
|
|
||||||
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.PolicyOrgIAMWriteModel.WriteModel)
|
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.PolicyOrgIAMWriteModel.WriteModel)
|
||||||
|
@ -30,7 +30,7 @@ func (r *CommandSide) addDefaultPasswordAgePolicy(ctx context.Context, iamAgg *i
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if addedPolicy.IsActive {
|
if addedPolicy.State == domain.PolicyStateActive {
|
||||||
return caos_errs.ThrowAlreadyExists(nil, "IAM-Lk0dS", "Errors.IAM.PasswordAgePolicy.AlreadyExists")
|
return caos_errs.ThrowAlreadyExists(nil, "IAM-Lk0dS", "Errors.IAM.PasswordAgePolicy.AlreadyExists")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,13 +45,13 @@ func (r *CommandSide) ChangeDefaultPasswordAgePolicy(ctx context.Context, policy
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if !existingPolicy.IsActive {
|
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||||
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-0oPew", "Errors.IAM.PasswordAgePolicy.NotFound")
|
return nil, caos_errs.ThrowNotFound(nil, "IAM-0oPew", "Errors.IAM.PasswordAgePolicy.NotFound")
|
||||||
}
|
}
|
||||||
|
|
||||||
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, policy.ExpireWarnDays, policy.MaxAgeDays)
|
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, policy.ExpireWarnDays, policy.MaxAgeDays)
|
||||||
if !hasChanged {
|
if !hasChanged {
|
||||||
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-4M9vs", "Errors.IAM.LabelPolicy.NotChanged")
|
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-4M9vs", "Errors.IAM.LabelPolicy.NotChanged")
|
||||||
}
|
}
|
||||||
|
|
||||||
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.PasswordAgePolicyWriteModel.WriteModel)
|
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.PasswordAgePolicyWriteModel.WriteModel)
|
||||||
|
@ -45,7 +45,7 @@ func (r *CommandSide) addDefaultPasswordComplexityPolicy(ctx context.Context, ia
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if addedPolicy.IsActive {
|
if addedPolicy.State == domain.PolicyStateActive {
|
||||||
return caos_errs.ThrowAlreadyExists(nil, "IAM-Lk0dS", "Errors.IAM.PasswordComplexityPolicy.AlreadyExists")
|
return caos_errs.ThrowAlreadyExists(nil, "IAM-Lk0dS", "Errors.IAM.PasswordComplexityPolicy.AlreadyExists")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,13 +64,13 @@ func (r *CommandSide) ChangeDefaultPasswordComplexityPolicy(ctx context.Context,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if !existingPolicy.IsActive {
|
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||||
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-0oPew", "Errors.IAM.PasswordAgePolicy.NotFound")
|
return nil, caos_errs.ThrowNotFound(nil, "IAM-0oPew", "Errors.IAM.PasswordAgePolicy.NotFound")
|
||||||
}
|
}
|
||||||
|
|
||||||
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, policy.MinLength, policy.HasLowercase, policy.HasUppercase, policy.HasNumber, policy.HasSymbol)
|
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, policy.MinLength, policy.HasLowercase, policy.HasUppercase, policy.HasNumber, policy.HasSymbol)
|
||||||
if !hasChanged {
|
if !hasChanged {
|
||||||
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-4M9vs", "Errors.IAM.LabelPolicy.NotChanged")
|
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-4M9vs", "Errors.IAM.LabelPolicy.NotChanged")
|
||||||
}
|
}
|
||||||
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.PasswordComplexityPolicyWriteModel.WriteModel)
|
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.PasswordComplexityPolicyWriteModel.WriteModel)
|
||||||
iamAgg.PushEvents(changedEvent)
|
iamAgg.PushEvents(changedEvent)
|
||||||
|
@ -30,7 +30,7 @@ func (r *CommandSide) addDefaultPasswordLockoutPolicy(ctx context.Context, iamAg
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if addedPolicy.IsActive {
|
if addedPolicy.State == domain.PolicyStateActive {
|
||||||
return caos_errs.ThrowAlreadyExists(nil, "IAM-0olDf", "Errors.IAM.PasswordLockoutPolicy.AlreadyExists")
|
return caos_errs.ThrowAlreadyExists(nil, "IAM-0olDf", "Errors.IAM.PasswordLockoutPolicy.AlreadyExists")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,13 +45,13 @@ func (r *CommandSide) ChangeDefaultPasswordLockoutPolicy(ctx context.Context, po
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if !existingPolicy.IsActive {
|
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||||
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-0oPew", "Errors.IAM.PasswordLockoutPolicy.NotFound")
|
return nil, caos_errs.ThrowNotFound(nil, "IAM-0oPew", "Errors.IAM.PasswordLockoutPolicy.NotFound")
|
||||||
}
|
}
|
||||||
|
|
||||||
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, policy.MaxAttempts, policy.ShowLockOutFailures)
|
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, policy.MaxAttempts, policy.ShowLockOutFailures)
|
||||||
if !hasChanged {
|
if !hasChanged {
|
||||||
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-4M9vs", "Errors.IAM.PasswordLockoutPolicy.NotChanged")
|
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-4M9vs", "Errors.IAM.PasswordLockoutPolicy.NotChanged")
|
||||||
}
|
}
|
||||||
|
|
||||||
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.PasswordLockoutPolicyWriteModel.WriteModel)
|
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.PasswordLockoutPolicyWriteModel.WriteModel)
|
||||||
|
@ -11,7 +11,7 @@ type IdentityProviderWriteModel struct {
|
|||||||
|
|
||||||
IDPConfigID string
|
IDPConfigID string
|
||||||
IDPProviderType domain.IdentityProviderType
|
IDPProviderType domain.IdentityProviderType
|
||||||
IsActive bool
|
State domain.IdentityProviderState
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wm *IdentityProviderWriteModel) Reduce() error {
|
func (wm *IdentityProviderWriteModel) Reduce() error {
|
||||||
@ -20,9 +20,9 @@ func (wm *IdentityProviderWriteModel) Reduce() error {
|
|||||||
case *policy.IdentityProviderAddedEvent:
|
case *policy.IdentityProviderAddedEvent:
|
||||||
wm.IDPConfigID = e.IDPConfigID
|
wm.IDPConfigID = e.IDPConfigID
|
||||||
wm.IDPProviderType = e.IDPProviderType
|
wm.IDPProviderType = e.IDPProviderType
|
||||||
wm.IsActive = true
|
wm.State = domain.IdentityProviderStateActive
|
||||||
case *policy.IdentityProviderRemovedEvent:
|
case *policy.IdentityProviderRemovedEvent:
|
||||||
wm.IsActive = false
|
wm.State = domain.IdentityProviderStateRemoved
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return wm.WriteModel.Reduce()
|
return wm.WriteModel.Reduce()
|
||||||
|
@ -2,15 +2,17 @@ package command
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||||
|
"github.com/caos/zitadel/internal/v2/domain"
|
||||||
"github.com/caos/zitadel/internal/v2/repository/member"
|
"github.com/caos/zitadel/internal/v2/repository/member"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MemberWriteModel struct {
|
type MemberWriteModel struct {
|
||||||
eventstore.WriteModel
|
eventstore.WriteModel
|
||||||
|
|
||||||
UserID string
|
UserID string
|
||||||
Roles []string
|
Roles []string
|
||||||
IsActive bool
|
|
||||||
|
State domain.MemberState
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMemberWriteModel(userID string) *MemberWriteModel {
|
func NewMemberWriteModel(userID string) *MemberWriteModel {
|
||||||
@ -25,12 +27,12 @@ func (wm *MemberWriteModel) Reduce() error {
|
|||||||
case *member.MemberAddedEvent:
|
case *member.MemberAddedEvent:
|
||||||
wm.UserID = e.UserID
|
wm.UserID = e.UserID
|
||||||
wm.Roles = e.Roles
|
wm.Roles = e.Roles
|
||||||
wm.IsActive = true
|
wm.State = domain.MemberStateActive
|
||||||
case *member.MemberChangedEvent:
|
case *member.MemberChangedEvent:
|
||||||
wm.Roles = e.Roles
|
wm.Roles = e.Roles
|
||||||
case *member.MemberRemovedEvent:
|
case *member.MemberRemovedEvent:
|
||||||
wm.Roles = nil
|
wm.Roles = nil
|
||||||
wm.IsActive = false
|
wm.State = domain.MemberStateRemoved
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return wm.WriteModel.Reduce()
|
return wm.WriteModel.Reduce()
|
||||||
|
@ -14,7 +14,7 @@ func (r *CommandSide) GetOrgIAMPolicy(ctx context.Context, orgID string) (*domai
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if policy.IsActive {
|
if policy.State == domain.PolicyStateActive {
|
||||||
return orgWriteModelToOrgIAMPolicy(policy), nil
|
return orgWriteModelToOrgIAMPolicy(policy), nil
|
||||||
}
|
}
|
||||||
return r.GetDefaultOrgIAMPolicy(ctx)
|
return r.GetDefaultOrgIAMPolicy(ctx)
|
||||||
@ -26,7 +26,7 @@ func (r *CommandSide) AddOrgIAMPolicy(ctx context.Context, policy *domain.OrgIAM
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if addedPolicy.IsActive {
|
if addedPolicy.State == domain.PolicyStateActive {
|
||||||
return nil, caos_errs.ThrowAlreadyExists(nil, "ORG-5M0ds", "Errors.Org.OrgIAMPolicy.AlreadyExists")
|
return nil, caos_errs.ThrowAlreadyExists(nil, "ORG-5M0ds", "Errors.Org.OrgIAMPolicy.AlreadyExists")
|
||||||
}
|
}
|
||||||
orgAgg := ORGAggregateFromWriteModel(&addedPolicy.PolicyOrgIAMWriteModel.WriteModel)
|
orgAgg := ORGAggregateFromWriteModel(&addedPolicy.PolicyOrgIAMWriteModel.WriteModel)
|
||||||
@ -45,13 +45,13 @@ func (r *CommandSide) ChangeOrgIAMPolicy(ctx context.Context, policy *domain.Org
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if !existingPolicy.IsActive {
|
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||||
return nil, caos_errs.ThrowAlreadyExists(nil, "ORG-2N9sd", "Errors.Org.OrgIAMPolicy.NotFound")
|
return nil, caos_errs.ThrowNotFound(nil, "ORG-2N9sd", "Errors.Org.OrgIAMPolicy.NotFound")
|
||||||
}
|
}
|
||||||
|
|
||||||
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, policy.UserLoginMustBeDomain)
|
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, policy.UserLoginMustBeDomain)
|
||||||
if !hasChanged {
|
if !hasChanged {
|
||||||
return nil, caos_errs.ThrowAlreadyExists(nil, "ORG-3M9ds", "Errors.Org.LabelPolicy.NotChanged")
|
return nil, caos_errs.ThrowPreconditionFailed(nil, "ORG-3M9ds", "Errors.Org.LabelPolicy.NotChanged")
|
||||||
}
|
}
|
||||||
|
|
||||||
orgAgg := ORGAggregateFromWriteModel(&existingPolicy.PolicyOrgIAMWriteModel.WriteModel)
|
orgAgg := ORGAggregateFromWriteModel(&existingPolicy.PolicyOrgIAMWriteModel.WriteModel)
|
||||||
|
@ -11,7 +11,7 @@ func (r *CommandSide) GetOrgPasswordComplexityPolicy(ctx context.Context, orgID
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if policy.IsActive {
|
if policy.State == domain.PolicyStateActive {
|
||||||
return orgWriteModelToPasswordComplexityPolicy(policy), nil
|
return orgWriteModelToPasswordComplexityPolicy(policy), nil
|
||||||
}
|
}
|
||||||
return r.GetDefaultPasswordComplexityPolicy(ctx)
|
return r.GetDefaultPasswordComplexityPolicy(ctx)
|
||||||
|
@ -2,6 +2,7 @@ package command
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||||
|
"github.com/caos/zitadel/internal/v2/domain"
|
||||||
"github.com/caos/zitadel/internal/v2/repository/policy"
|
"github.com/caos/zitadel/internal/v2/repository/policy"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -10,7 +11,8 @@ type LabelPolicyWriteModel struct {
|
|||||||
|
|
||||||
PrimaryColor string
|
PrimaryColor string
|
||||||
SecondaryColor string
|
SecondaryColor string
|
||||||
IsActive bool
|
|
||||||
|
State domain.PolicyState
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wm *LabelPolicyWriteModel) Reduce() error {
|
func (wm *LabelPolicyWriteModel) Reduce() error {
|
||||||
@ -19,7 +21,7 @@ func (wm *LabelPolicyWriteModel) Reduce() error {
|
|||||||
case *policy.LabelPolicyAddedEvent:
|
case *policy.LabelPolicyAddedEvent:
|
||||||
wm.PrimaryColor = e.PrimaryColor
|
wm.PrimaryColor = e.PrimaryColor
|
||||||
wm.SecondaryColor = e.SecondaryColor
|
wm.SecondaryColor = e.SecondaryColor
|
||||||
wm.IsActive = true
|
wm.State = domain.PolicyStateActive
|
||||||
case *policy.LabelPolicyChangedEvent:
|
case *policy.LabelPolicyChangedEvent:
|
||||||
if e.PrimaryColor != nil {
|
if e.PrimaryColor != nil {
|
||||||
wm.PrimaryColor = *e.PrimaryColor
|
wm.PrimaryColor = *e.PrimaryColor
|
||||||
@ -28,7 +30,7 @@ func (wm *LabelPolicyWriteModel) Reduce() error {
|
|||||||
wm.SecondaryColor = *e.SecondaryColor
|
wm.SecondaryColor = *e.SecondaryColor
|
||||||
}
|
}
|
||||||
case *policy.LabelPolicyRemovedEvent:
|
case *policy.LabelPolicyRemovedEvent:
|
||||||
wm.IsActive = false
|
wm.State = domain.PolicyStateRemoved
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return wm.WriteModel.Reduce()
|
return wm.WriteModel.Reduce()
|
||||||
|
@ -8,8 +8,8 @@ import (
|
|||||||
|
|
||||||
type SecondFactorWriteModel struct {
|
type SecondFactorWriteModel struct {
|
||||||
eventstore.WriteModel
|
eventstore.WriteModel
|
||||||
MFAType domain.SecondFactorType
|
MFAType domain.SecondFactorType
|
||||||
IsActive bool
|
State domain.FactorState
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wm *SecondFactorWriteModel) Reduce() error {
|
func (wm *SecondFactorWriteModel) Reduce() error {
|
||||||
@ -17,10 +17,10 @@ func (wm *SecondFactorWriteModel) Reduce() error {
|
|||||||
switch e := event.(type) {
|
switch e := event.(type) {
|
||||||
case *policy.SecondFactorAddedEvent:
|
case *policy.SecondFactorAddedEvent:
|
||||||
wm.MFAType = e.MFAType
|
wm.MFAType = e.MFAType
|
||||||
wm.IsActive = true
|
wm.State = domain.FactorStateActive
|
||||||
case *policy.SecondFactorRemovedEvent:
|
case *policy.SecondFactorRemovedEvent:
|
||||||
wm.MFAType = e.MFAType
|
wm.MFAType = e.MFAType
|
||||||
wm.IsActive = false
|
wm.State = domain.FactorStateRemoved
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return wm.WriteModel.Reduce()
|
return wm.WriteModel.Reduce()
|
||||||
@ -28,8 +28,8 @@ func (wm *SecondFactorWriteModel) Reduce() error {
|
|||||||
|
|
||||||
type MultiFactoryWriteModel struct {
|
type MultiFactoryWriteModel struct {
|
||||||
eventstore.WriteModel
|
eventstore.WriteModel
|
||||||
MFAType domain.MultiFactorType
|
MFAType domain.MultiFactorType
|
||||||
IsActive bool
|
State domain.FactorState
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wm *MultiFactoryWriteModel) Reduce() error {
|
func (wm *MultiFactoryWriteModel) Reduce() error {
|
||||||
@ -37,10 +37,10 @@ func (wm *MultiFactoryWriteModel) Reduce() error {
|
|||||||
switch e := event.(type) {
|
switch e := event.(type) {
|
||||||
case *policy.MultiFactorAddedEvent:
|
case *policy.MultiFactorAddedEvent:
|
||||||
wm.MFAType = e.MFAType
|
wm.MFAType = e.MFAType
|
||||||
wm.IsActive = true
|
wm.State = domain.FactorStateActive
|
||||||
case *policy.MultiFactorRemovedEvent:
|
case *policy.MultiFactorRemovedEvent:
|
||||||
wm.MFAType = e.MFAType
|
wm.MFAType = e.MFAType
|
||||||
wm.IsActive = false
|
wm.State = domain.FactorStateRemoved
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return wm.WriteModel.Reduce()
|
return wm.WriteModel.Reduce()
|
||||||
|
@ -14,7 +14,7 @@ type LoginPolicyWriteModel struct {
|
|||||||
AllowExternalIDP bool
|
AllowExternalIDP bool
|
||||||
ForceMFA bool
|
ForceMFA bool
|
||||||
PasswordlessType domain.PasswordlessType
|
PasswordlessType domain.PasswordlessType
|
||||||
IsActive bool
|
State domain.PolicyState
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wm *LoginPolicyWriteModel) Reduce() error {
|
func (wm *LoginPolicyWriteModel) Reduce() error {
|
||||||
@ -26,7 +26,7 @@ func (wm *LoginPolicyWriteModel) Reduce() error {
|
|||||||
wm.AllowExternalIDP = e.AllowExternalIDP
|
wm.AllowExternalIDP = e.AllowExternalIDP
|
||||||
wm.ForceMFA = e.ForceMFA
|
wm.ForceMFA = e.ForceMFA
|
||||||
wm.PasswordlessType = e.PasswordlessType
|
wm.PasswordlessType = e.PasswordlessType
|
||||||
wm.IsActive = true
|
wm.State = domain.PolicyStateActive
|
||||||
case *policy.LoginPolicyChangedEvent:
|
case *policy.LoginPolicyChangedEvent:
|
||||||
if e.AllowRegister != nil {
|
if e.AllowRegister != nil {
|
||||||
wm.AllowRegister = *e.AllowRegister
|
wm.AllowRegister = *e.AllowRegister
|
||||||
@ -44,7 +44,7 @@ func (wm *LoginPolicyWriteModel) Reduce() error {
|
|||||||
wm.PasswordlessType = *e.PasswordlessType
|
wm.PasswordlessType = *e.PasswordlessType
|
||||||
}
|
}
|
||||||
case *policy.LoginPolicyRemovedEvent:
|
case *policy.LoginPolicyRemovedEvent:
|
||||||
wm.IsActive = false
|
wm.State = domain.PolicyStateRemoved
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return wm.WriteModel.Reduce()
|
return wm.WriteModel.Reduce()
|
||||||
|
@ -2,6 +2,7 @@ package command
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||||
|
"github.com/caos/zitadel/internal/v2/domain"
|
||||||
"github.com/caos/zitadel/internal/v2/repository/policy"
|
"github.com/caos/zitadel/internal/v2/repository/policy"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -9,7 +10,7 @@ type PolicyOrgIAMWriteModel struct {
|
|||||||
eventstore.WriteModel
|
eventstore.WriteModel
|
||||||
|
|
||||||
UserLoginMustBeDomain bool
|
UserLoginMustBeDomain bool
|
||||||
IsActive bool
|
State domain.PolicyState
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wm *PolicyOrgIAMWriteModel) Reduce() error {
|
func (wm *PolicyOrgIAMWriteModel) Reduce() error {
|
||||||
@ -17,7 +18,7 @@ func (wm *PolicyOrgIAMWriteModel) Reduce() error {
|
|||||||
switch e := event.(type) {
|
switch e := event.(type) {
|
||||||
case *policy.OrgIAMPolicyAddedEvent:
|
case *policy.OrgIAMPolicyAddedEvent:
|
||||||
wm.UserLoginMustBeDomain = e.UserLoginMustBeDomain
|
wm.UserLoginMustBeDomain = e.UserLoginMustBeDomain
|
||||||
wm.IsActive = true
|
wm.State = domain.PolicyStateActive
|
||||||
case *policy.OrgIAMPolicyChangedEvent:
|
case *policy.OrgIAMPolicyChangedEvent:
|
||||||
if e.UserLoginMustBeDomain != nil {
|
if e.UserLoginMustBeDomain != nil {
|
||||||
wm.UserLoginMustBeDomain = *e.UserLoginMustBeDomain
|
wm.UserLoginMustBeDomain = *e.UserLoginMustBeDomain
|
||||||
|
@ -2,6 +2,7 @@ package command
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||||
|
"github.com/caos/zitadel/internal/v2/domain"
|
||||||
"github.com/caos/zitadel/internal/v2/repository/policy"
|
"github.com/caos/zitadel/internal/v2/repository/policy"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -10,7 +11,7 @@ type PasswordAgePolicyWriteModel struct {
|
|||||||
|
|
||||||
ExpireWarnDays uint64
|
ExpireWarnDays uint64
|
||||||
MaxAgeDays uint64
|
MaxAgeDays uint64
|
||||||
IsActive bool
|
State domain.PolicyState
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wm *PasswordAgePolicyWriteModel) Reduce() error {
|
func (wm *PasswordAgePolicyWriteModel) Reduce() error {
|
||||||
@ -19,7 +20,7 @@ func (wm *PasswordAgePolicyWriteModel) Reduce() error {
|
|||||||
case *policy.PasswordAgePolicyAddedEvent:
|
case *policy.PasswordAgePolicyAddedEvent:
|
||||||
wm.ExpireWarnDays = e.ExpireWarnDays
|
wm.ExpireWarnDays = e.ExpireWarnDays
|
||||||
wm.MaxAgeDays = e.MaxAgeDays
|
wm.MaxAgeDays = e.MaxAgeDays
|
||||||
wm.IsActive = true
|
wm.State = domain.PolicyStateActive
|
||||||
case *policy.PasswordAgePolicyChangedEvent:
|
case *policy.PasswordAgePolicyChangedEvent:
|
||||||
if e.ExpireWarnDays != nil {
|
if e.ExpireWarnDays != nil {
|
||||||
wm.ExpireWarnDays = *e.ExpireWarnDays
|
wm.ExpireWarnDays = *e.ExpireWarnDays
|
||||||
@ -28,7 +29,7 @@ func (wm *PasswordAgePolicyWriteModel) Reduce() error {
|
|||||||
wm.ExpireWarnDays = *e.ExpireWarnDays
|
wm.ExpireWarnDays = *e.ExpireWarnDays
|
||||||
}
|
}
|
||||||
case *policy.PasswordAgePolicyRemovedEvent:
|
case *policy.PasswordAgePolicyRemovedEvent:
|
||||||
wm.IsActive = false
|
wm.State = domain.PolicyStateRemoved
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return wm.WriteModel.Reduce()
|
return wm.WriteModel.Reduce()
|
||||||
|
@ -2,6 +2,7 @@ package command
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||||
|
"github.com/caos/zitadel/internal/v2/domain"
|
||||||
"github.com/caos/zitadel/internal/v2/repository/policy"
|
"github.com/caos/zitadel/internal/v2/repository/policy"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -13,7 +14,7 @@ type PasswordComplexityPolicyWriteModel struct {
|
|||||||
HasUpperCase bool
|
HasUpperCase bool
|
||||||
HasNumber bool
|
HasNumber bool
|
||||||
HasSymbol bool
|
HasSymbol bool
|
||||||
IsActive bool
|
State domain.PolicyState
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wm *PasswordComplexityPolicyWriteModel) Reduce() error {
|
func (wm *PasswordComplexityPolicyWriteModel) Reduce() error {
|
||||||
@ -25,7 +26,7 @@ func (wm *PasswordComplexityPolicyWriteModel) Reduce() error {
|
|||||||
wm.HasUpperCase = e.HasUpperCase
|
wm.HasUpperCase = e.HasUpperCase
|
||||||
wm.HasNumber = e.HasNumber
|
wm.HasNumber = e.HasNumber
|
||||||
wm.HasSymbol = e.HasSymbol
|
wm.HasSymbol = e.HasSymbol
|
||||||
wm.IsActive = true
|
wm.State = domain.PolicyStateActive
|
||||||
case *policy.PasswordComplexityPolicyChangedEvent:
|
case *policy.PasswordComplexityPolicyChangedEvent:
|
||||||
if e.MinLength != nil {
|
if e.MinLength != nil {
|
||||||
wm.MinLength = *e.MinLength
|
wm.MinLength = *e.MinLength
|
||||||
@ -43,7 +44,7 @@ func (wm *PasswordComplexityPolicyWriteModel) Reduce() error {
|
|||||||
wm.HasSymbol = *e.HasSymbol
|
wm.HasSymbol = *e.HasSymbol
|
||||||
}
|
}
|
||||||
case *policy.PasswordComplexityPolicyRemovedEvent:
|
case *policy.PasswordComplexityPolicyRemovedEvent:
|
||||||
wm.IsActive = false
|
wm.State = domain.PolicyStateRemoved
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return wm.WriteModel.Reduce()
|
return wm.WriteModel.Reduce()
|
||||||
|
@ -2,6 +2,7 @@ package command
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||||
|
"github.com/caos/zitadel/internal/v2/domain"
|
||||||
"github.com/caos/zitadel/internal/v2/repository/policy"
|
"github.com/caos/zitadel/internal/v2/repository/policy"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -10,7 +11,7 @@ type PasswordLockoutPolicyWriteModel struct {
|
|||||||
|
|
||||||
MaxAttempts uint64
|
MaxAttempts uint64
|
||||||
ShowLockOutFailures bool
|
ShowLockOutFailures bool
|
||||||
IsActive bool
|
State domain.PolicyState
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wm *PasswordLockoutPolicyWriteModel) Reduce() error {
|
func (wm *PasswordLockoutPolicyWriteModel) Reduce() error {
|
||||||
@ -19,7 +20,7 @@ func (wm *PasswordLockoutPolicyWriteModel) Reduce() error {
|
|||||||
case *policy.PasswordLockoutPolicyAddedEvent:
|
case *policy.PasswordLockoutPolicyAddedEvent:
|
||||||
wm.MaxAttempts = e.MaxAttempts
|
wm.MaxAttempts = e.MaxAttempts
|
||||||
wm.ShowLockOutFailures = e.ShowLockOutFailures
|
wm.ShowLockOutFailures = e.ShowLockOutFailures
|
||||||
wm.IsActive = true
|
wm.State = domain.PolicyStateActive
|
||||||
case *policy.PasswordLockoutPolicyChangedEvent:
|
case *policy.PasswordLockoutPolicyChangedEvent:
|
||||||
if e.MaxAttempts != nil {
|
if e.MaxAttempts != nil {
|
||||||
wm.MaxAttempts = *e.MaxAttempts
|
wm.MaxAttempts = *e.MaxAttempts
|
||||||
@ -28,7 +29,7 @@ func (wm *PasswordLockoutPolicyWriteModel) Reduce() error {
|
|||||||
wm.ShowLockOutFailures = *e.ShowLockOutFailures
|
wm.ShowLockOutFailures = *e.ShowLockOutFailures
|
||||||
}
|
}
|
||||||
case *policy.PasswordLockoutPolicyRemovedEvent:
|
case *policy.PasswordLockoutPolicyRemovedEvent:
|
||||||
wm.IsActive = false
|
wm.State = domain.PolicyStateRemoved
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return wm.WriteModel.Reduce()
|
return wm.WriteModel.Reduce()
|
||||||
|
@ -8,19 +8,19 @@ import (
|
|||||||
"github.com/caos/zitadel/internal/v2/repository/user"
|
"github.com/caos/zitadel/internal/v2/repository/user"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *CommandSide) AddUser(ctx context.Context, user *domain.User) (*domain.User, error) {
|
func (r *CommandSide) AddUser(ctx context.Context, orgID string, user *domain.User) (*domain.User, error) {
|
||||||
if !user.IsValid() {
|
if !user.IsValid() {
|
||||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-2N9fs", "Errors.User.Invalid")
|
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-2N9fs", "Errors.User.Invalid")
|
||||||
}
|
}
|
||||||
|
|
||||||
if user.Human != nil {
|
if user.Human != nil {
|
||||||
human, err := r.AddHuman(ctx, user.ResourceOwner, user.UserName, user.Human)
|
human, err := r.AddHuman(ctx, orgID, user.UserName, user.Human)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &domain.User{UserName: user.UserName, Human: human}, nil
|
return &domain.User{UserName: user.UserName, Human: human}, nil
|
||||||
} else if user.Machine != nil {
|
} else if user.Machine != nil {
|
||||||
machine, err := r.AddMachine(ctx, user.ResourceOwner, user.UserName, user.Machine)
|
machine, err := r.AddMachine(ctx, orgID, user.UserName, user.Machine)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -29,13 +29,13 @@ func (r *CommandSide) AddUser(ctx context.Context, user *domain.User) (*domain.U
|
|||||||
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-8K0df", "Errors.User.TypeUndefined")
|
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-8K0df", "Errors.User.TypeUndefined")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *CommandSide) RegisterUser(ctx context.Context, user *domain.User) (*domain.User, error) {
|
func (r *CommandSide) RegisterUser(ctx context.Context, orgID string, user *domain.User) (*domain.User, error) {
|
||||||
if !user.IsValid() {
|
if !user.IsValid() {
|
||||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-2N9fs", "Errors.User.Invalid")
|
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-2N9fs", "Errors.User.Invalid")
|
||||||
}
|
}
|
||||||
|
|
||||||
if user.Human != nil {
|
if user.Human != nil {
|
||||||
human, err := r.RegisterHuman(ctx, user.ResourceOwner, user.UserName, user.Human, nil)
|
human, err := r.RegisterHuman(ctx, orgID, user.UserName, user.Human, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -44,13 +44,46 @@ func (r *CommandSide) RegisterUser(ctx context.Context, user *domain.User) (*dom
|
|||||||
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-8K0df", "Errors.User.TypeUndefined")
|
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-8K0df", "Errors.User.TypeUndefined")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *CommandSide) ChangeUsername(ctx context.Context, orgID, userID, userName string) error {
|
||||||
|
if orgID == "" || userID == "" || userName == "" {
|
||||||
|
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-2N9fs", "Errors.IDMissing")
|
||||||
|
}
|
||||||
|
existingUser, err := r.userWriteModelByID(ctx, userID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if existingUser.UserState == domain.UserStateUnspecified || existingUser.UserState == domain.UserStateDeleted {
|
||||||
|
return caos_errs.ThrowNotFound(nil, "COMMAND-5N9ds", "Errors.User.NotFound")
|
||||||
|
}
|
||||||
|
if existingUser.UserName == userName {
|
||||||
|
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-2M9fs", "Errors.User.UsernameNotChanged")
|
||||||
|
}
|
||||||
|
|
||||||
|
orgIAMPolicy, err := r.GetOrgIAMPolicy(ctx, orgID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := CheckOrgIAMPolicyForUserName(userName, orgIAMPolicy); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
userAgg := UserAggregateFromWriteModel(&existingUser.WriteModel)
|
||||||
|
userAgg.PushEvents(user.NewUsernameChangedEvent(ctx, userName))
|
||||||
|
//TODO: Check Uniqueness
|
||||||
|
//TODO: release old username, set new unique username
|
||||||
|
|
||||||
|
return r.eventstore.PushAggregate(ctx, existingUser, userAgg)
|
||||||
|
}
|
||||||
|
|
||||||
func (r *CommandSide) DeactivateUser(ctx context.Context, userID string) (*domain.User, error) {
|
func (r *CommandSide) DeactivateUser(ctx context.Context, userID string) (*domain.User, error) {
|
||||||
|
if userID == "" {
|
||||||
|
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-m0gDf", "Errors.User.UserIDMissing")
|
||||||
|
}
|
||||||
existingUser, err := r.userWriteModelByID(ctx, userID)
|
existingUser, err := r.userWriteModelByID(ctx, userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if existingUser.UserState != domain.UserStateUnspecified || existingUser.UserState != domain.UserStateDeleted {
|
if existingUser.UserState == domain.UserStateUnspecified || existingUser.UserState == domain.UserStateDeleted {
|
||||||
return nil, caos_errs.ThrowAlreadyExists(nil, "COMMAND-3M9ds", "Errors.User.NotFound")
|
return nil, caos_errs.ThrowNotFound(nil, "COMMAND-3M9ds", "Errors.User.NotFound")
|
||||||
}
|
}
|
||||||
if existingUser.UserState == domain.UserStateInactive {
|
if existingUser.UserState == domain.UserStateInactive {
|
||||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-5M0sf", "Errors.User.AlreadyInactive")
|
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-5M0sf", "Errors.User.AlreadyInactive")
|
||||||
@ -66,12 +99,15 @@ func (r *CommandSide) DeactivateUser(ctx context.Context, userID string) (*domai
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *CommandSide) ReactivateUser(ctx context.Context, userID string) (*domain.User, error) {
|
func (r *CommandSide) ReactivateUser(ctx context.Context, userID string) (*domain.User, error) {
|
||||||
|
if userID == "" {
|
||||||
|
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-4M9ds", "Errors.User.UserIDMissing")
|
||||||
|
}
|
||||||
existingUser, err := r.userWriteModelByID(ctx, userID)
|
existingUser, err := r.userWriteModelByID(ctx, userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if existingUser.UserState != domain.UserStateUnspecified || existingUser.UserState != domain.UserStateDeleted {
|
if existingUser.UserState == domain.UserStateUnspecified || existingUser.UserState == domain.UserStateDeleted {
|
||||||
return nil, caos_errs.ThrowAlreadyExists(nil, "COMMAND-4M0sd", "Errors.User.NotFound")
|
return nil, caos_errs.ThrowNotFound(nil, "COMMAND-4M0sd", "Errors.User.NotFound")
|
||||||
}
|
}
|
||||||
if existingUser.UserState != domain.UserStateInactive {
|
if existingUser.UserState != domain.UserStateInactive {
|
||||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-6M0sf", "Errors.User.NotInactive")
|
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-6M0sf", "Errors.User.NotInactive")
|
||||||
@ -87,12 +123,15 @@ func (r *CommandSide) ReactivateUser(ctx context.Context, userID string) (*domai
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *CommandSide) LockUser(ctx context.Context, userID string) (*domain.User, error) {
|
func (r *CommandSide) LockUser(ctx context.Context, userID string) (*domain.User, error) {
|
||||||
|
if userID == "" {
|
||||||
|
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-2M0sd", "Errors.User.UserIDMissing")
|
||||||
|
}
|
||||||
existingUser, err := r.userWriteModelByID(ctx, userID)
|
existingUser, err := r.userWriteModelByID(ctx, userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if existingUser.UserState != domain.UserStateUnspecified || existingUser.UserState != domain.UserStateDeleted {
|
if existingUser.UserState == domain.UserStateUnspecified || existingUser.UserState == domain.UserStateDeleted {
|
||||||
return nil, caos_errs.ThrowAlreadyExists(nil, "COMMAND-5M9fs", "Errors.User.NotFound")
|
return nil, caos_errs.ThrowNotFound(nil, "COMMAND-5M9fs", "Errors.User.NotFound")
|
||||||
}
|
}
|
||||||
if existingUser.UserState != domain.UserStateActive && existingUser.UserState != domain.UserStateInitial {
|
if existingUser.UserState != domain.UserStateActive && existingUser.UserState != domain.UserStateInitial {
|
||||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-2M9fs", "Errors.User.ShouldBeActiveOrInitial")
|
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-2M9fs", "Errors.User.ShouldBeActiveOrInitial")
|
||||||
@ -108,12 +147,15 @@ func (r *CommandSide) LockUser(ctx context.Context, userID string) (*domain.User
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *CommandSide) UnlockUser(ctx context.Context, userID string) (*domain.User, error) {
|
func (r *CommandSide) UnlockUser(ctx context.Context, userID string) (*domain.User, error) {
|
||||||
|
if userID == "" {
|
||||||
|
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-M0dse", "Errors.User.UserIDMissing")
|
||||||
|
}
|
||||||
existingUser, err := r.userWriteModelByID(ctx, userID)
|
existingUser, err := r.userWriteModelByID(ctx, userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if existingUser.UserState != domain.UserStateUnspecified || existingUser.UserState != domain.UserStateDeleted {
|
if existingUser.UserState == domain.UserStateUnspecified || existingUser.UserState == domain.UserStateDeleted {
|
||||||
return nil, caos_errs.ThrowAlreadyExists(nil, "COMMAND-M0dos", "Errors.User.NotFound")
|
return nil, caos_errs.ThrowNotFound(nil, "COMMAND-M0dos", "Errors.User.NotFound")
|
||||||
}
|
}
|
||||||
if existingUser.UserState != domain.UserStateLocked {
|
if existingUser.UserState != domain.UserStateLocked {
|
||||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-4M0ds", "Errors.User.NotLocked")
|
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-4M0ds", "Errors.User.NotLocked")
|
||||||
@ -129,16 +171,20 @@ func (r *CommandSide) UnlockUser(ctx context.Context, userID string) (*domain.Us
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *CommandSide) RemoveUser(ctx context.Context, userID string) error {
|
func (r *CommandSide) RemoveUser(ctx context.Context, userID string) error {
|
||||||
|
if userID == "" {
|
||||||
|
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-2M0ds", "Errors.User.UserIDMissing")
|
||||||
|
}
|
||||||
existingUser, err := r.userWriteModelByID(ctx, userID)
|
existingUser, err := r.userWriteModelByID(ctx, userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if existingUser.UserState != domain.UserStateDeleted {
|
if existingUser.UserState == domain.UserStateUnspecified || existingUser.UserState == domain.UserStateDeleted {
|
||||||
return caos_errs.ThrowAlreadyExists(nil, "COMMAND-5M0od", "Errors.User.NotFound")
|
return caos_errs.ThrowNotFound(nil, "COMMAND-5M0od", "Errors.User.NotFound")
|
||||||
}
|
}
|
||||||
userAgg := UserAggregateFromWriteModel(&existingUser.WriteModel)
|
userAgg := UserAggregateFromWriteModel(&existingUser.WriteModel)
|
||||||
userAgg.PushEvents(user.NewUserRemovedEvent(ctx))
|
userAgg.PushEvents(user.NewUserRemovedEvent(ctx))
|
||||||
//TODO: release unqie username
|
//TODO: release unqie username
|
||||||
|
//TODO: remove user grants
|
||||||
|
|
||||||
return r.eventstore.PushAggregate(ctx, existingUser, userAgg)
|
return r.eventstore.PushAggregate(ctx, existingUser, userAgg)
|
||||||
}
|
}
|
||||||
|
@ -57,6 +57,13 @@ func writeModelToEmail(wm *HumanEmailWriteModel) *domain.Email {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func writeModelToPhone(wm *HumanPhoneWriteModel) *domain.Phone {
|
||||||
|
return &domain.Phone{
|
||||||
|
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
|
||||||
|
PhoneNumber: wm.Phone,
|
||||||
|
IsPhoneVerified: wm.IsPhoneVerified,
|
||||||
|
}
|
||||||
|
}
|
||||||
func writeModelToAddress(wm *HumanAddressWriteModel) *domain.Address {
|
func writeModelToAddress(wm *HumanAddressWriteModel) *domain.Address {
|
||||||
return &domain.Address{
|
return &domain.Address{
|
||||||
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
|
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
|
||||||
|
@ -27,9 +27,13 @@ func (r *CommandSide) AddHuman(ctx context.Context, orgID, username string, huma
|
|||||||
|
|
||||||
addedHuman := NewHumanWriteModel(human.AggregateID)
|
addedHuman := NewHumanWriteModel(human.AggregateID)
|
||||||
//TODO: Check Unique Username
|
//TODO: Check Unique Username
|
||||||
human.CheckOrgIAMPolicy(username, orgIAMPolicy)
|
if err := human.CheckOrgIAMPolicy(username, orgIAMPolicy); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
human.SetNamesAsDisplayname()
|
human.SetNamesAsDisplayname()
|
||||||
human.HashPasswordIfExisting(pwPolicy, r.userPasswordAlg, true)
|
if err := human.HashPasswordIfExisting(pwPolicy, r.userPasswordAlg, true); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
userAgg := UserAggregateFromWriteModel(&addedHuman.WriteModel)
|
userAgg := UserAggregateFromWriteModel(&addedHuman.WriteModel)
|
||||||
addEvent := user.NewHumanAddedEvent(
|
addEvent := user.NewHumanAddedEvent(
|
||||||
@ -107,9 +111,13 @@ func (r *CommandSide) RegisterHuman(ctx context.Context, orgID, username string,
|
|||||||
|
|
||||||
addedHuman := NewHumanWriteModel(human.AggregateID)
|
addedHuman := NewHumanWriteModel(human.AggregateID)
|
||||||
//TODO: Check Unique Username or unique external idp
|
//TODO: Check Unique Username or unique external idp
|
||||||
human.CheckOrgIAMPolicy(username, orgIAMPolicy)
|
if err := human.CheckOrgIAMPolicy(username, orgIAMPolicy); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
human.SetNamesAsDisplayname()
|
human.SetNamesAsDisplayname()
|
||||||
human.HashPasswordIfExisting(pwPolicy, r.userPasswordAlg, true)
|
if err := human.HashPasswordIfExisting(pwPolicy, r.userPasswordAlg, true); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
userAgg := UserAggregateFromWriteModel(&addedHuman.WriteModel)
|
userAgg := UserAggregateFromWriteModel(&addedHuman.WriteModel)
|
||||||
addEvent := user.NewHumanRegisteredEvent(
|
addEvent := user.NewHumanRegisteredEvent(
|
||||||
@ -144,7 +152,7 @@ func (r *CommandSide) RegisterHuman(ctx context.Context, orgID, username string,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
user.NewHumanInitialCodeAddedEvent(ctx, initCode.Code, initCode.Expiry)
|
userAgg.PushEvents(user.NewHumanInitialCodeAddedEvent(ctx, initCode.Code, initCode.Expiry))
|
||||||
}
|
}
|
||||||
|
|
||||||
if human.Email != nil && human.EmailAddress != "" && human.IsEmailVerified {
|
if human.Email != nil && human.EmailAddress != "" && human.IsEmailVerified {
|
||||||
@ -155,7 +163,9 @@ func (r *CommandSide) RegisterHuman(ctx context.Context, orgID, username string,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
user.NewHumanPhoneCodeAddedEvent(ctx, phoneCode.Code, phoneCode.Expiry)
|
userAgg.PushEvents(user.NewHumanPhoneCodeAddedEvent(ctx, phoneCode.Code, phoneCode.Expiry))
|
||||||
|
} else if human.Phone != nil && human.PhoneNumber != "" && human.IsPhoneVerified {
|
||||||
|
userAgg.PushEvents(user.NewHumanPhoneVerifiedEvent(ctx))
|
||||||
}
|
}
|
||||||
|
|
||||||
err = r.eventstore.PushAggregate(ctx, addedHuman, userAgg)
|
err = r.eventstore.PushAggregate(ctx, addedHuman, userAgg)
|
||||||
@ -165,3 +175,31 @@ func (r *CommandSide) RegisterHuman(ctx context.Context, orgID, username string,
|
|||||||
|
|
||||||
return writeModelToHuman(addedHuman), nil
|
return writeModelToHuman(addedHuman), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *CommandSide) ResendInitialMail(ctx context.Context, userID, email string) (err error) {
|
||||||
|
if userID == "" {
|
||||||
|
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-2M9fs", "Errors.User.UserIDMissing")
|
||||||
|
}
|
||||||
|
|
||||||
|
existingEmail, err := r.emailWriteModel(ctx, userID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if existingEmail.UserState == domain.UserStateUnspecified || existingEmail.UserState == domain.UserStateDeleted {
|
||||||
|
return caos_errs.ThrowNotFound(nil, "COMMAND-2M9df", "Errors.User.NotFound")
|
||||||
|
}
|
||||||
|
if existingEmail.UserState != domain.UserStateInitial {
|
||||||
|
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-2M9sd", "Errors.User.AlreadyInitialised")
|
||||||
|
}
|
||||||
|
userAgg := UserAggregateFromWriteModel(&existingEmail.WriteModel)
|
||||||
|
if email != "" && existingEmail.Email != email {
|
||||||
|
changedEvent, _ := existingEmail.NewChangedEvent(ctx, email)
|
||||||
|
userAgg.PushEvents(changedEvent)
|
||||||
|
}
|
||||||
|
initCode, err := domain.NewInitUserCode(r.initializeUserCode)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
userAgg.PushEvents(user.NewHumanInitialCodeAddedEvent(ctx, initCode.Code, initCode.Expiry))
|
||||||
|
return r.eventstore.PushAggregate(ctx, existingEmail, userAgg)
|
||||||
|
}
|
||||||
|
@ -12,12 +12,12 @@ func (r *CommandSide) ChangeHumanAddress(ctx context.Context, address *domain.Ad
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if existingAddress.UserState == domain.UserStateUnspecified || existingAddress.UserState == domain.UserStateDeleted {
|
if existingAddress.State == domain.AddressStateUnspecified || existingAddress.State == domain.AddressStateRemoved {
|
||||||
return nil, caos_errs.ThrowAlreadyExists(nil, "COMMAND-0pLdo", "Errors.User.Address.NotFound")
|
return nil, caos_errs.ThrowNotFound(nil, "COMMAND-0pLdo", "Errors.User.Address.NotFound")
|
||||||
}
|
}
|
||||||
changedEvent, hasChanged := existingAddress.NewChangedEvent(ctx, address.Country, address.Locality, address.PostalCode, address.Region, address.StreetAddress)
|
changedEvent, hasChanged := existingAddress.NewChangedEvent(ctx, address.Country, address.Locality, address.PostalCode, address.Region, address.StreetAddress)
|
||||||
if !hasChanged {
|
if !hasChanged {
|
||||||
return nil, caos_errs.ThrowAlreadyExists(nil, "COMMAND-3M0cs", "Errors.User.Address.NotChanged")
|
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-3M0cs", "Errors.User.Address.NotChanged")
|
||||||
}
|
}
|
||||||
userAgg := UserAggregateFromWriteModel(&existingAddress.WriteModel)
|
userAgg := UserAggregateFromWriteModel(&existingAddress.WriteModel)
|
||||||
userAgg.PushEvents(changedEvent)
|
userAgg.PushEvents(changedEvent)
|
||||||
|
@ -16,7 +16,7 @@ type HumanAddressWriteModel struct {
|
|||||||
Region string
|
Region string
|
||||||
StreetAddress string
|
StreetAddress string
|
||||||
|
|
||||||
UserState domain.UserState
|
State domain.AddressState
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHumanAddressWriteModel(userID string) *HumanAddressWriteModel {
|
func NewHumanAddressWriteModel(userID string) *HumanAddressWriteModel {
|
||||||
@ -49,14 +49,14 @@ func (wm *HumanAddressWriteModel) Reduce() error {
|
|||||||
wm.PostalCode = e.PostalCode
|
wm.PostalCode = e.PostalCode
|
||||||
wm.Region = e.Region
|
wm.Region = e.Region
|
||||||
wm.StreetAddress = e.StreetAddress
|
wm.StreetAddress = e.StreetAddress
|
||||||
wm.UserState = domain.UserStateActive
|
wm.State = domain.AddressStateActive
|
||||||
case *user.HumanRegisteredEvent:
|
case *user.HumanRegisteredEvent:
|
||||||
wm.Country = e.Country
|
wm.Country = e.Country
|
||||||
wm.Locality = e.Locality
|
wm.Locality = e.Locality
|
||||||
wm.PostalCode = e.PostalCode
|
wm.PostalCode = e.PostalCode
|
||||||
wm.Region = e.Region
|
wm.Region = e.Region
|
||||||
wm.StreetAddress = e.StreetAddress
|
wm.StreetAddress = e.StreetAddress
|
||||||
wm.UserState = domain.UserStateActive
|
wm.State = domain.AddressStateActive
|
||||||
case *user.HumanAddressChangedEvent:
|
case *user.HumanAddressChangedEvent:
|
||||||
if e.Country != nil {
|
if e.Country != nil {
|
||||||
wm.Country = *e.Country
|
wm.Country = *e.Country
|
||||||
@ -74,7 +74,7 @@ func (wm *HumanAddressWriteModel) Reduce() error {
|
|||||||
wm.StreetAddress = *e.StreetAddress
|
wm.StreetAddress = *e.StreetAddress
|
||||||
}
|
}
|
||||||
case *user.UserRemovedEvent:
|
case *user.UserRemovedEvent:
|
||||||
wm.UserState = domain.UserStateDeleted
|
wm.State = domain.AddressStateRemoved
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return wm.WriteModel.Reduce()
|
return wm.WriteModel.Reduce()
|
||||||
|
@ -5,10 +5,11 @@ import (
|
|||||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||||
"github.com/caos/zitadel/internal/v2/domain"
|
"github.com/caos/zitadel/internal/v2/domain"
|
||||||
|
"github.com/caos/zitadel/internal/v2/repository/user"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *CommandSide) ChangeHumanEmail(ctx context.Context, email *domain.Email) (*domain.Email, error) {
|
func (r *CommandSide) ChangeHumanEmail(ctx context.Context, email *domain.Email) (*domain.Email, error) {
|
||||||
if !email.IsValid() {
|
if !email.IsValid() || email.AggregateID == "" {
|
||||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-4M9sf", "Errors.Email.Invalid")
|
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-4M9sf", "Errors.Email.Invalid")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -17,15 +18,25 @@ func (r *CommandSide) ChangeHumanEmail(ctx context.Context, email *domain.Email)
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if existingEmail.UserState == domain.UserStateUnspecified || existingEmail.UserState == domain.UserStateDeleted {
|
if existingEmail.UserState == domain.UserStateUnspecified || existingEmail.UserState == domain.UserStateDeleted {
|
||||||
return nil, caos_errs.ThrowAlreadyExists(nil, "COMMAND-0Pe4r", "Errors.User.Email.NotFound")
|
return nil, caos_errs.ThrowNotFound(nil, "COMMAND-0Pe4r", "Errors.User.Email.NotFound")
|
||||||
}
|
}
|
||||||
changedEvent, hasChanged := existingEmail.NewChangedEvent(ctx, email.EmailAddress)
|
changedEvent, hasChanged := existingEmail.NewChangedEvent(ctx, email.EmailAddress)
|
||||||
if !hasChanged {
|
if !hasChanged {
|
||||||
return nil, caos_errs.ThrowAlreadyExists(nil, "COMMAND-2M9fs", "Errors.User.Email.NotChanged")
|
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-2M9fs", "Errors.User.Email.NotChanged")
|
||||||
}
|
}
|
||||||
userAgg := UserAggregateFromWriteModel(&existingEmail.WriteModel)
|
userAgg := UserAggregateFromWriteModel(&existingEmail.WriteModel)
|
||||||
userAgg.PushEvents(changedEvent)
|
userAgg.PushEvents(changedEvent)
|
||||||
|
|
||||||
|
if email.IsEmailVerified {
|
||||||
|
userAgg.PushEvents(user.NewHumanEmailVerifiedEvent(ctx))
|
||||||
|
} else {
|
||||||
|
emailCode, err := domain.NewEmailCode(r.emailVerificationCode)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
userAgg.PushEvents(user.NewHumanEmailCodeAddedEvent(ctx, emailCode.Code, emailCode.Expiry))
|
||||||
|
}
|
||||||
|
|
||||||
err = r.eventstore.PushAggregate(ctx, existingEmail, userAgg)
|
err = r.eventstore.PushAggregate(ctx, existingEmail, userAgg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -34,6 +45,34 @@ func (r *CommandSide) ChangeHumanEmail(ctx context.Context, email *domain.Email)
|
|||||||
return writeModelToEmail(existingEmail), nil
|
return writeModelToEmail(existingEmail), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *CommandSide) CreateHumanEmailVerificationCode(ctx context.Context, userID string) error {
|
||||||
|
if userID == "" {
|
||||||
|
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-4M0ds", "Errors.User.UserIDMissing")
|
||||||
|
}
|
||||||
|
|
||||||
|
existingEmail, err := r.emailWriteModel(ctx, userID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if existingEmail.UserState == domain.UserStateUnspecified || existingEmail.UserState == domain.UserStateDeleted {
|
||||||
|
return caos_errs.ThrowNotFound(nil, "COMMAND-0Pe4r", "Errors.User.Email.NotFound")
|
||||||
|
}
|
||||||
|
if existingEmail.UserState == domain.UserStateInitial {
|
||||||
|
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-E3fbw", "Errors.User.NotInitialised")
|
||||||
|
}
|
||||||
|
if existingEmail.IsEmailVerified {
|
||||||
|
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-3M9ds", "Errors.User.Email.AlreadyVerified")
|
||||||
|
}
|
||||||
|
userAgg := UserAggregateFromWriteModel(&existingEmail.WriteModel)
|
||||||
|
emailCode, err := domain.NewEmailCode(r.emailVerificationCode)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
userAgg.PushEvents(user.NewHumanEmailCodeAddedEvent(ctx, emailCode.Code, emailCode.Expiry))
|
||||||
|
|
||||||
|
return r.eventstore.PushAggregate(ctx, existingEmail, userAgg)
|
||||||
|
}
|
||||||
|
|
||||||
func (r *CommandSide) emailWriteModel(ctx context.Context, userID string) (writeModel *HumanEmailWriteModel, err error) {
|
func (r *CommandSide) emailWriteModel(ctx context.Context, userID string) (writeModel *HumanEmailWriteModel, err error) {
|
||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
|
@ -44,15 +44,18 @@ func (wm *HumanEmailWriteModel) Reduce() error {
|
|||||||
switch e := event.(type) {
|
switch e := event.(type) {
|
||||||
case *user.HumanAddedEvent:
|
case *user.HumanAddedEvent:
|
||||||
wm.Email = e.EmailAddress
|
wm.Email = e.EmailAddress
|
||||||
wm.UserState = domain.UserStateActive
|
wm.UserState = domain.UserStateInitial
|
||||||
case *user.HumanRegisteredEvent:
|
case *user.HumanRegisteredEvent:
|
||||||
wm.Email = e.EmailAddress
|
wm.Email = e.EmailAddress
|
||||||
wm.UserState = domain.UserStateActive
|
wm.UserState = domain.UserStateInitial
|
||||||
case *user.HumanEmailChangedEvent:
|
case *user.HumanEmailChangedEvent:
|
||||||
wm.Email = e.EmailAddress
|
wm.Email = e.EmailAddress
|
||||||
wm.IsEmailVerified = false
|
wm.IsEmailVerified = false
|
||||||
case *user.HumanEmailVerifiedEvent:
|
case *user.HumanEmailVerifiedEvent:
|
||||||
wm.IsEmailVerified = true
|
wm.IsEmailVerified = true
|
||||||
|
if wm.UserState == domain.UserStateInitial {
|
||||||
|
wm.UserState = domain.UserStateActive
|
||||||
|
}
|
||||||
case *user.UserRemovedEvent:
|
case *user.UserRemovedEvent:
|
||||||
wm.UserState = domain.UserStateDeleted
|
wm.UserState = domain.UserStateDeleted
|
||||||
}
|
}
|
||||||
|
52
internal/v2/command/user_human_externalidp.go
Normal file
52
internal/v2/command/user_human_externalidp.go
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||||
|
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||||
|
"github.com/caos/zitadel/internal/v2/domain"
|
||||||
|
"github.com/caos/zitadel/internal/v2/repository/user"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (r *CommandSide) RemoveHumanExternalIDP(ctx context.Context, externalIDP *domain.ExternalIDP) error {
|
||||||
|
return r.removeHumanExternalIDP(ctx, externalIDP, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *CommandSide) removeHumanExternalIDP(ctx context.Context, externalIDP *domain.ExternalIDP, cascade bool) error {
|
||||||
|
if externalIDP.IsValid() {
|
||||||
|
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-3M9ds", "Errors.IDMissing")
|
||||||
|
}
|
||||||
|
|
||||||
|
existingExternalIDP, err := r.externalIDPWriteModelByID(ctx, externalIDP.AggregateID, externalIDP.IDPConfigID, externalIDP.ExternalUserID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if existingExternalIDP.State == domain.ExternalIDPStateUnspecified || existingExternalIDP.State == domain.ExternalIDPStateRemoved {
|
||||||
|
return caos_errs.ThrowNotFound(nil, "COMMAND-5M0ds", "Errors.User.ExternalIDP.NotFound")
|
||||||
|
}
|
||||||
|
userAgg := UserAggregateFromWriteModel(&existingExternalIDP.WriteModel)
|
||||||
|
if !cascade {
|
||||||
|
userAgg.PushEvents(
|
||||||
|
user.NewHumanExternalIDPRemovedEvent(ctx, externalIDP.IDPConfigID, externalIDP.ExternalUserID),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
userAgg.PushEvents(
|
||||||
|
user.NewHumanExternalIDPCascadeRemovedEvent(ctx, externalIDP.IDPConfigID, externalIDP.ExternalUserID),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: Release unique externalidp
|
||||||
|
return r.eventstore.PushAggregate(ctx, existingExternalIDP, userAgg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *CommandSide) externalIDPWriteModelByID(ctx context.Context, userID, idpConfigID, externalUserID string) (writeModel *HumanExternalIDPWriteModel, err error) {
|
||||||
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
|
writeModel = NewHumanExternalIDPWriteModel(userID, idpConfigID, externalUserID)
|
||||||
|
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return writeModel, nil
|
||||||
|
}
|
72
internal/v2/command/user_human_externalidp_model.go
Normal file
72
internal/v2/command/user_human_externalidp_model.go
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||||
|
"github.com/caos/zitadel/internal/v2/domain"
|
||||||
|
"github.com/caos/zitadel/internal/v2/repository/user"
|
||||||
|
)
|
||||||
|
|
||||||
|
type HumanExternalIDPWriteModel struct {
|
||||||
|
eventstore.WriteModel
|
||||||
|
|
||||||
|
IDPConfigID string
|
||||||
|
ExternalUserID string
|
||||||
|
DisplayName string
|
||||||
|
|
||||||
|
State domain.ExternalIDPState
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHumanExternalIDPWriteModel(userID, idpConfigID, externalUserID string) *HumanExternalIDPWriteModel {
|
||||||
|
return &HumanExternalIDPWriteModel{
|
||||||
|
WriteModel: eventstore.WriteModel{
|
||||||
|
AggregateID: userID,
|
||||||
|
},
|
||||||
|
IDPConfigID: idpConfigID,
|
||||||
|
ExternalUserID: externalUserID,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *HumanExternalIDPWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||||
|
for _, event := range events {
|
||||||
|
switch e := event.(type) {
|
||||||
|
case *user.HumanExternalIDPAddedEvent:
|
||||||
|
if wm.IDPConfigID == e.IDPConfigID && wm.ExternalUserID == e.UserID {
|
||||||
|
wm.AppendEvents(e)
|
||||||
|
}
|
||||||
|
case *user.HumanExternalIDPRemovedEvent:
|
||||||
|
if wm.IDPConfigID == e.IDPConfigID && wm.ExternalUserID == e.UserID {
|
||||||
|
wm.AppendEvents(e)
|
||||||
|
}
|
||||||
|
case *user.HumanExternalIDPCascadeRemovedEvent:
|
||||||
|
if wm.IDPConfigID == e.IDPConfigID && wm.ExternalUserID == e.UserID {
|
||||||
|
wm.AppendEvents(e)
|
||||||
|
}
|
||||||
|
case *user.UserRemovedEvent:
|
||||||
|
wm.AppendEvents(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *HumanExternalIDPWriteModel) Reduce() error {
|
||||||
|
for _, event := range wm.Events {
|
||||||
|
switch e := event.(type) {
|
||||||
|
case *user.HumanExternalIDPAddedEvent:
|
||||||
|
wm.IDPConfigID = e.IDPConfigID
|
||||||
|
wm.DisplayName = e.DisplayName
|
||||||
|
wm.ExternalUserID = e.UserID
|
||||||
|
wm.State = domain.ExternalIDPStateActive
|
||||||
|
case *user.HumanExternalIDPRemovedEvent:
|
||||||
|
wm.State = domain.ExternalIDPStateRemoved
|
||||||
|
case *user.HumanExternalIDPCascadeRemovedEvent:
|
||||||
|
wm.State = domain.ExternalIDPStateRemoved
|
||||||
|
case *user.UserRemovedEvent:
|
||||||
|
wm.State = domain.ExternalIDPStateRemoved
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return wm.WriteModel.Reduce()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *HumanExternalIDPWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||||
|
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, user.AggregateType).
|
||||||
|
AggregateIDs(wm.AggregateID)
|
||||||
|
}
|
@ -76,6 +76,8 @@ func (wm *HumanWriteModel) Reduce() error {
|
|||||||
wm.reduceHumanAddedEvent(e)
|
wm.reduceHumanAddedEvent(e)
|
||||||
case *user.HumanRegisteredEvent:
|
case *user.HumanRegisteredEvent:
|
||||||
wm.reduceHumanRegisteredEvent(e)
|
wm.reduceHumanRegisteredEvent(e)
|
||||||
|
case *user.UsernameChangedEvent:
|
||||||
|
wm.UserName = e.UserName
|
||||||
case *user.HumanProfileChangedEvent:
|
case *user.HumanProfileChangedEvent:
|
||||||
wm.reduceHumanProfileChangedEvent(e)
|
wm.reduceHumanProfileChangedEvent(e)
|
||||||
case *user.HumanEmailChangedEvent:
|
case *user.HumanEmailChangedEvent:
|
||||||
|
41
internal/v2/command/user_human_otp.go
Normal file
41
internal/v2/command/user_human_otp.go
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||||
|
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||||
|
"github.com/caos/zitadel/internal/v2/domain"
|
||||||
|
"github.com/caos/zitadel/internal/v2/repository/user"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (r *CommandSide) RemoveHumanOTP(ctx context.Context, userID string) error {
|
||||||
|
if userID == "" {
|
||||||
|
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-5M0sd", "Errors.User.UserIDMissing")
|
||||||
|
}
|
||||||
|
|
||||||
|
existingOTP, err := r.otpWriteModelByID(ctx, userID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if existingOTP.State == domain.OTPStateUnspecified || existingOTP.State == domain.OTPStateRemoved {
|
||||||
|
return caos_errs.ThrowNotFound(nil, "COMMAND-5M0ds", "Errors.User.OTP.NotFound")
|
||||||
|
}
|
||||||
|
userAgg := UserAggregateFromWriteModel(&existingOTP.WriteModel)
|
||||||
|
userAgg.PushEvents(
|
||||||
|
user.NewHumanOTPRemovedEvent(ctx),
|
||||||
|
)
|
||||||
|
|
||||||
|
return r.eventstore.PushAggregate(ctx, existingOTP, userAgg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *CommandSide) otpWriteModelByID(ctx context.Context, userID string) (writeModel *HumanOTPWriteModel, err error) {
|
||||||
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
|
writeModel = NewHumanOTPWriteModel(userID)
|
||||||
|
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return writeModel, nil
|
||||||
|
}
|
57
internal/v2/command/user_human_otp_model.go
Normal file
57
internal/v2/command/user_human_otp_model.go
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/caos/zitadel/internal/crypto"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||||
|
"github.com/caos/zitadel/internal/v2/domain"
|
||||||
|
"github.com/caos/zitadel/internal/v2/repository/user"
|
||||||
|
)
|
||||||
|
|
||||||
|
type HumanOTPWriteModel struct {
|
||||||
|
eventstore.WriteModel
|
||||||
|
|
||||||
|
Secret *crypto.CryptoValue
|
||||||
|
|
||||||
|
State domain.OTPState
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHumanOTPWriteModel(userID string) *HumanOTPWriteModel {
|
||||||
|
return &HumanOTPWriteModel{
|
||||||
|
WriteModel: eventstore.WriteModel{
|
||||||
|
AggregateID: userID,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *HumanOTPWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||||
|
for _, event := range events {
|
||||||
|
switch e := event.(type) {
|
||||||
|
case *user.HumanOTPAddedEvent:
|
||||||
|
wm.AppendEvents(e)
|
||||||
|
case *user.HumanOTPRemovedEvent:
|
||||||
|
wm.AppendEvents(e)
|
||||||
|
case *user.UserRemovedEvent:
|
||||||
|
wm.AppendEvents(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *HumanOTPWriteModel) Reduce() error {
|
||||||
|
for _, event := range wm.Events {
|
||||||
|
switch e := event.(type) {
|
||||||
|
case *user.HumanOTPAddedEvent:
|
||||||
|
wm.Secret = e.Secret
|
||||||
|
wm.State = domain.OTPStateActive
|
||||||
|
case *user.HumanOTPRemovedEvent:
|
||||||
|
wm.State = domain.OTPStateRemoved
|
||||||
|
case *user.UserRemovedEvent:
|
||||||
|
wm.State = domain.OTPStateRemoved
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return wm.WriteModel.Reduce()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *HumanOTPWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||||
|
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, user.AggregateType).
|
||||||
|
AggregateIDs(wm.AggregateID)
|
||||||
|
}
|
107
internal/v2/command/user_human_password.go
Normal file
107
internal/v2/command/user_human_password.go
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/caos/zitadel/internal/crypto"
|
||||||
|
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||||
|
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||||
|
"github.com/caos/zitadel/internal/v2/domain"
|
||||||
|
"github.com/caos/zitadel/internal/v2/repository/user"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (r *CommandSide) SetOneTimePassword(ctx context.Context, orgID, userID, passwordString string) (err error) {
|
||||||
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
|
existingPassword, err := r.passwordWriteModel(ctx, userID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
password := &domain.Password{
|
||||||
|
SecretString: passwordString,
|
||||||
|
ChangeRequired: true,
|
||||||
|
}
|
||||||
|
return r.changePassword(ctx, orgID, userID, "", password, existingPassword)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *CommandSide) ChangePassword(ctx context.Context, orgID, userID, oldPassword, newPassword, userAgentID string) (err error) {
|
||||||
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
|
existingPassword, err := r.passwordWriteModel(ctx, userID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if existingPassword.Secret != nil {
|
||||||
|
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-Fds3s", "Errors.User.Password.Empty")
|
||||||
|
}
|
||||||
|
ctx, spanPasswordComparison := tracing.NewNamedSpan(ctx, "crypto.CompareHash")
|
||||||
|
err = crypto.CompareHash(existingPassword.Secret, []byte(oldPassword), r.userPasswordAlg)
|
||||||
|
spanPasswordComparison.EndWithError(err)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return caos_errs.ThrowInvalidArgument(nil, "COMMAND-3M0fs", "Errors.User.Password.Invalid")
|
||||||
|
}
|
||||||
|
password := &domain.Password{
|
||||||
|
SecretString: newPassword,
|
||||||
|
ChangeRequired: true,
|
||||||
|
}
|
||||||
|
return r.changePassword(ctx, orgID, userID, userAgentID, password, existingPassword)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *CommandSide) changePassword(ctx context.Context, orgID, userID, userAgentID string, password *domain.Password, existingPassword *HumanPasswordWriteModel) (err error) {
|
||||||
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
|
if userID == "" {
|
||||||
|
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-B8hY3", "Errors.User.UserIDMissing")
|
||||||
|
}
|
||||||
|
if existingPassword.UserState == domain.UserStateUnspecified || existingPassword.UserState == domain.UserStateDeleted {
|
||||||
|
return caos_errs.ThrowNotFound(nil, "COMMAND-G8dh3", "Errors.User.Email.NotFound")
|
||||||
|
}
|
||||||
|
if existingPassword.UserState == domain.UserStateInitial {
|
||||||
|
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-M9dse", "Errors.User.NotInitialised")
|
||||||
|
}
|
||||||
|
pwPolicy, err := r.GetOrgPasswordComplexityPolicy(ctx, orgID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := password.HashPasswordIfExisting(pwPolicy, r.userPasswordAlg); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
userAgg := UserAggregateFromWriteModel(&existingPassword.WriteModel)
|
||||||
|
userAgg.PushEvents(user.NewHumanPasswordChangedEvent(ctx, password.SecretCrypto, password.ChangeRequired, userAgentID))
|
||||||
|
return r.eventstore.PushAggregate(ctx, existingPassword, userAgg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *CommandSide) RequestSetPassword(ctx context.Context, userID string, notifyType domain.NotificationType) (err error) {
|
||||||
|
existingHuman, err := r.userWriteModelByID(ctx, userID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if existingHuman.UserState == domain.UserStateUnspecified || existingHuman.UserState == domain.UserStateDeleted {
|
||||||
|
return caos_errs.ThrowNotFound(nil, "COMMAND-Hj9ds", "Errors.User.NotFound")
|
||||||
|
}
|
||||||
|
if existingHuman.UserState == domain.UserStateInitial {
|
||||||
|
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-2M9sd", "Errors.User.NotInitialised")
|
||||||
|
}
|
||||||
|
userAgg := UserAggregateFromWriteModel(&existingHuman.WriteModel)
|
||||||
|
passwordCode, err := domain.NewPasswordCode(r.passwordVerificationCode)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
userAgg.PushEvents(user.NewHumanPasswordCodeAddedEvent(ctx, passwordCode.Code, passwordCode.Expiry, notifyType))
|
||||||
|
return r.eventstore.PushAggregate(ctx, existingHuman, userAgg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *CommandSide) passwordWriteModel(ctx context.Context, userID string) (writeModel *HumanPasswordWriteModel, err error) {
|
||||||
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
|
writeModel = NewHumanPasswordWriteModel(userID)
|
||||||
|
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return writeModel, nil
|
||||||
|
}
|
70
internal/v2/command/user_human_password_model.go
Normal file
70
internal/v2/command/user_human_password_model.go
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/caos/zitadel/internal/crypto"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||||
|
"github.com/caos/zitadel/internal/v2/domain"
|
||||||
|
"github.com/caos/zitadel/internal/v2/repository/user"
|
||||||
|
)
|
||||||
|
|
||||||
|
type HumanPasswordWriteModel struct {
|
||||||
|
eventstore.WriteModel
|
||||||
|
|
||||||
|
Secret *crypto.CryptoValue
|
||||||
|
SecretChangeRequired bool
|
||||||
|
|
||||||
|
UserState domain.UserState
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHumanPasswordWriteModel(userID string) *HumanPasswordWriteModel {
|
||||||
|
return &HumanPasswordWriteModel{
|
||||||
|
WriteModel: eventstore.WriteModel{
|
||||||
|
AggregateID: userID,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *HumanPasswordWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||||
|
for _, event := range events {
|
||||||
|
switch e := event.(type) {
|
||||||
|
case *user.HumanPasswordChangedEvent:
|
||||||
|
wm.AppendEvents(e)
|
||||||
|
case *user.HumanAddedEvent, *user.HumanRegisteredEvent:
|
||||||
|
wm.AppendEvents(e)
|
||||||
|
case *user.HumanEmailVerifiedEvent:
|
||||||
|
wm.AppendEvents(e)
|
||||||
|
case *user.UserRemovedEvent:
|
||||||
|
wm.AppendEvents(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *HumanPasswordWriteModel) Reduce() error {
|
||||||
|
for _, event := range wm.Events {
|
||||||
|
switch e := event.(type) {
|
||||||
|
case *user.HumanAddedEvent:
|
||||||
|
wm.Secret = e.Secret
|
||||||
|
wm.SecretChangeRequired = e.ChangeRequired
|
||||||
|
wm.UserState = domain.UserStateInitial
|
||||||
|
case *user.HumanRegisteredEvent:
|
||||||
|
wm.Secret = e.Secret
|
||||||
|
wm.SecretChangeRequired = e.ChangeRequired
|
||||||
|
wm.UserState = domain.UserStateActive
|
||||||
|
case *user.HumanPasswordChangedEvent:
|
||||||
|
wm.Secret = e.Secret
|
||||||
|
wm.SecretChangeRequired = e.ChangeRequired
|
||||||
|
case *user.HumanEmailVerifiedEvent:
|
||||||
|
if wm.UserState == domain.UserStateInitial {
|
||||||
|
wm.UserState = domain.UserStateActive
|
||||||
|
}
|
||||||
|
case *user.UserRemovedEvent:
|
||||||
|
wm.UserState = domain.UserStateDeleted
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return wm.WriteModel.Reduce()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *HumanPasswordWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||||
|
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, user.AggregateType).
|
||||||
|
AggregateIDs(wm.AggregateID)
|
||||||
|
}
|
101
internal/v2/command/user_human_phone.go
Normal file
101
internal/v2/command/user_human_phone.go
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||||
|
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||||
|
"github.com/caos/zitadel/internal/v2/domain"
|
||||||
|
"github.com/caos/zitadel/internal/v2/repository/user"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (r *CommandSide) ChangeHumanPhone(ctx context.Context, phone *domain.Phone) (*domain.Phone, error) {
|
||||||
|
if !phone.IsValid() {
|
||||||
|
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-6M0ds", "Errors.Phone.Invalid")
|
||||||
|
}
|
||||||
|
|
||||||
|
existingPhone, err := r.phoneWriteModel(ctx, phone.AggregateID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if existingPhone.State == domain.PhoneStateUnspecified || existingPhone.State == domain.PhoneStateRemoved {
|
||||||
|
return nil, caos_errs.ThrowNotFound(nil, "COMMAND-5M0ds", "Errors.User.Phone.NotFound")
|
||||||
|
}
|
||||||
|
changedEvent, hasChanged := existingPhone.NewChangedEvent(ctx, phone.PhoneNumber)
|
||||||
|
if !hasChanged {
|
||||||
|
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-wF94r", "Errors.User.Phone.NotChanged")
|
||||||
|
}
|
||||||
|
userAgg := UserAggregateFromWriteModel(&existingPhone.WriteModel)
|
||||||
|
userAgg.PushEvents(changedEvent)
|
||||||
|
|
||||||
|
if phone.IsPhoneVerified {
|
||||||
|
userAgg.PushEvents(user.NewHumanPhoneVerifiedEvent(ctx))
|
||||||
|
} else {
|
||||||
|
phoneCode, err := domain.NewPhoneCode(r.phoneVerificationCode)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
userAgg.PushEvents(user.NewHumanPhoneCodeAddedEvent(ctx, phoneCode.Code, phoneCode.Expiry))
|
||||||
|
}
|
||||||
|
|
||||||
|
err = r.eventstore.PushAggregate(ctx, existingPhone, userAgg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return writeModelToPhone(existingPhone), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *CommandSide) CreateHumanPhoneVerificationCode(ctx context.Context, userID string) error {
|
||||||
|
if userID == "" {
|
||||||
|
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-4M0ds", "Errors.User.UserIDMissing")
|
||||||
|
}
|
||||||
|
|
||||||
|
existingPhone, err := r.phoneWriteModel(ctx, userID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if existingPhone.State == domain.PhoneStateUnspecified || existingPhone.State == domain.PhoneStateRemoved {
|
||||||
|
return caos_errs.ThrowNotFound(nil, "COMMAND-2M9fs", "Errors.User.Phone.NotFound")
|
||||||
|
}
|
||||||
|
if existingPhone.IsPhoneVerified {
|
||||||
|
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-2M9sf", "Errors.User.Phone.AlreadyVerified")
|
||||||
|
}
|
||||||
|
userAgg := UserAggregateFromWriteModel(&existingPhone.WriteModel)
|
||||||
|
phoneCode, err := domain.NewPhoneCode(r.phoneVerificationCode)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
userAgg.PushEvents(user.NewHumanPhoneCodeAddedEvent(ctx, phoneCode.Code, phoneCode.Expiry))
|
||||||
|
return r.eventstore.PushAggregate(ctx, existingPhone, userAgg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *CommandSide) RemoveHumanPhone(ctx context.Context, userID string) error {
|
||||||
|
if userID == "" {
|
||||||
|
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-6M0ds", "Errors.User.UserIDMissing")
|
||||||
|
}
|
||||||
|
|
||||||
|
existingPhone, err := r.phoneWriteModel(ctx, userID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if existingPhone.State == domain.PhoneStateUnspecified || existingPhone.State == domain.PhoneStateRemoved {
|
||||||
|
return caos_errs.ThrowNotFound(nil, "COMMAND-5M0ds", "Errors.User.Phone.NotFound")
|
||||||
|
}
|
||||||
|
userAgg := UserAggregateFromWriteModel(&existingPhone.WriteModel)
|
||||||
|
userAgg.PushEvents(
|
||||||
|
user.NewHumanPhoneRemovedEvent(ctx),
|
||||||
|
)
|
||||||
|
return r.eventstore.PushAggregate(ctx, existingPhone, userAgg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *CommandSide) phoneWriteModel(ctx context.Context, userID string) (writeModel *HumanPhoneWriteModel, err error) {
|
||||||
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
|
writeModel = NewHumanPhoneWriteModel(userID)
|
||||||
|
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return writeModel, nil
|
||||||
|
}
|
88
internal/v2/command/user_human_phone_model.go
Normal file
88
internal/v2/command/user_human_phone_model.go
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||||
|
"github.com/caos/zitadel/internal/v2/domain"
|
||||||
|
"github.com/caos/zitadel/internal/v2/repository/user"
|
||||||
|
)
|
||||||
|
|
||||||
|
type HumanPhoneWriteModel struct {
|
||||||
|
eventstore.WriteModel
|
||||||
|
|
||||||
|
Phone string
|
||||||
|
IsPhoneVerified bool
|
||||||
|
|
||||||
|
State domain.PhoneState
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHumanPhoneWriteModel(userID string) *HumanPhoneWriteModel {
|
||||||
|
return &HumanPhoneWriteModel{
|
||||||
|
WriteModel: eventstore.WriteModel{
|
||||||
|
AggregateID: userID,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *HumanPhoneWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||||
|
for _, event := range events {
|
||||||
|
switch e := event.(type) {
|
||||||
|
case *user.HumanAddedEvent, *user.HumanRegisteredEvent:
|
||||||
|
wm.AppendEvents(e)
|
||||||
|
case *user.HumanPhoneChangedEvent:
|
||||||
|
wm.AppendEvents(e)
|
||||||
|
case *user.HumanPhoneVerifiedEvent:
|
||||||
|
wm.AppendEvents(e)
|
||||||
|
case *user.HumanPhoneRemovedEvent:
|
||||||
|
wm.AppendEvents(e)
|
||||||
|
case *user.UserRemovedEvent:
|
||||||
|
wm.AppendEvents(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *HumanPhoneWriteModel) Reduce() error {
|
||||||
|
for _, event := range wm.Events {
|
||||||
|
switch e := event.(type) {
|
||||||
|
case *user.HumanAddedEvent:
|
||||||
|
if e.PhoneNumber != "" {
|
||||||
|
wm.Phone = e.PhoneNumber
|
||||||
|
wm.State = domain.PhoneStateActive
|
||||||
|
}
|
||||||
|
case *user.HumanRegisteredEvent:
|
||||||
|
if e.PhoneNumber != "" {
|
||||||
|
wm.Phone = e.PhoneNumber
|
||||||
|
wm.State = domain.PhoneStateActive
|
||||||
|
}
|
||||||
|
case *user.HumanPhoneChangedEvent:
|
||||||
|
wm.Phone = e.PhoneNumber
|
||||||
|
wm.IsPhoneVerified = false
|
||||||
|
wm.State = domain.PhoneStateActive
|
||||||
|
case *user.HumanPhoneVerifiedEvent:
|
||||||
|
wm.IsPhoneVerified = true
|
||||||
|
case *user.HumanPhoneRemovedEvent:
|
||||||
|
wm.State = domain.PhoneStateRemoved
|
||||||
|
case *user.UserRemovedEvent:
|
||||||
|
wm.State = domain.PhoneStateRemoved
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return wm.WriteModel.Reduce()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *HumanPhoneWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||||
|
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, user.AggregateType).
|
||||||
|
AggregateIDs(wm.AggregateID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *HumanPhoneWriteModel) NewChangedEvent(
|
||||||
|
ctx context.Context,
|
||||||
|
phone string,
|
||||||
|
) (*user.HumanPhoneChangedEvent, bool) {
|
||||||
|
hasChanged := false
|
||||||
|
changedEvent := user.NewHumanPhoneChangedEvent(ctx)
|
||||||
|
if wm.Phone != phone {
|
||||||
|
hasChanged = true
|
||||||
|
changedEvent.PhoneNumber = phone
|
||||||
|
}
|
||||||
|
return changedEvent, hasChanged
|
||||||
|
}
|
@ -8,7 +8,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (r *CommandSide) ChangeHumanProfile(ctx context.Context, profile *domain.Profile) (*domain.Profile, error) {
|
func (r *CommandSide) ChangeHumanProfile(ctx context.Context, profile *domain.Profile) (*domain.Profile, error) {
|
||||||
if !profile.IsValid() {
|
if !profile.IsValid() && profile.AggregateID != "" {
|
||||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-8io0d", "Errors.User.Profile.Invalid")
|
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-8io0d", "Errors.User.Profile.Invalid")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -17,11 +17,11 @@ func (r *CommandSide) ChangeHumanProfile(ctx context.Context, profile *domain.Pr
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if existingProfile.UserState == domain.UserStateUnspecified || existingProfile.UserState == domain.UserStateDeleted {
|
if existingProfile.UserState == domain.UserStateUnspecified || existingProfile.UserState == domain.UserStateDeleted {
|
||||||
return nil, caos_errs.ThrowAlreadyExists(nil, "COMMAND-3M9sd", "Errors.User.Profile.NotFound")
|
return nil, caos_errs.ThrowNotFound(nil, "COMMAND-3M9sd", "Errors.User.Profile.NotFound")
|
||||||
}
|
}
|
||||||
changedEvent, hasChanged := existingProfile.NewChangedEvent(ctx, profile.FirstName, profile.LastName, profile.NickName, profile.DisplayName, profile.PreferredLanguage, domain.Gender(profile.Gender))
|
changedEvent, hasChanged := existingProfile.NewChangedEvent(ctx, profile.FirstName, profile.LastName, profile.NickName, profile.DisplayName, profile.PreferredLanguage, domain.Gender(profile.Gender))
|
||||||
if !hasChanged {
|
if !hasChanged {
|
||||||
return nil, caos_errs.ThrowAlreadyExists(nil, "COMMAND-2M0fs", "Errors.User.Profile.NotChanged")
|
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-2M0fs", "Errors.User.Profile.NotChanged")
|
||||||
}
|
}
|
||||||
userAgg := UserAggregateFromWriteModel(&existingProfile.WriteModel)
|
userAgg := UserAggregateFromWriteModel(&existingProfile.WriteModel)
|
||||||
userAgg.PushEvents(changedEvent)
|
userAgg.PushEvents(changedEvent)
|
||||||
|
50
internal/v2/command/user_human_webauthn.go
Normal file
50
internal/v2/command/user_human_webauthn.go
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||||
|
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||||
|
"github.com/caos/zitadel/internal/v2/domain"
|
||||||
|
"github.com/caos/zitadel/internal/v2/repository/user"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (r *CommandSide) RemoveHumanU2F(ctx context.Context, userID, webAuthNID string) error {
|
||||||
|
event := user.NewHumanU2FRemovedEvent(ctx, webAuthNID)
|
||||||
|
return r.removeHumanWebAuthN(ctx, userID, webAuthNID, event)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *CommandSide) RemoveHumanPasswordless(ctx context.Context, userID, webAuthNID string) error {
|
||||||
|
event := user.NewHumanPasswordlessRemovedEvent(ctx, webAuthNID)
|
||||||
|
return r.removeHumanWebAuthN(ctx, userID, webAuthNID, event)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *CommandSide) removeHumanWebAuthN(ctx context.Context, userID, webAuthNID string, event eventstore.EventPusher) error {
|
||||||
|
if userID == "" || webAuthNID == "" {
|
||||||
|
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-6M9de", "Errors.IDMissing")
|
||||||
|
}
|
||||||
|
|
||||||
|
existingWebAuthN, err := r.webauthNWriteModelByID(ctx, userID, webAuthNID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if existingWebAuthN.State == domain.WebAuthNStateUnspecified || existingWebAuthN.State == domain.WebAuthNStateRemoved {
|
||||||
|
return caos_errs.ThrowNotFound(nil, "COMMAND-5M0ds", "Errors.User.ExternalIDP.NotFound")
|
||||||
|
}
|
||||||
|
userAgg := UserAggregateFromWriteModel(&existingWebAuthN.WriteModel)
|
||||||
|
userAgg.PushEvents(event)
|
||||||
|
|
||||||
|
return r.eventstore.PushAggregate(ctx, existingWebAuthN, userAgg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *CommandSide) webauthNWriteModelByID(ctx context.Context, userID, webAuthNID string) (writeModel *HumanWebAuthNWriteModel, err error) {
|
||||||
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
|
defer func() { span.EndWithError(err) }()
|
||||||
|
|
||||||
|
writeModel = NewHumanWebAuthNWriteModel(userID, webAuthNID)
|
||||||
|
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return writeModel, nil
|
||||||
|
}
|
61
internal/v2/command/user_human_webauthn_model.go
Normal file
61
internal/v2/command/user_human_webauthn_model.go
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||||
|
"github.com/caos/zitadel/internal/v2/domain"
|
||||||
|
"github.com/caos/zitadel/internal/v2/repository/user"
|
||||||
|
)
|
||||||
|
|
||||||
|
type HumanWebAuthNWriteModel struct {
|
||||||
|
eventstore.WriteModel
|
||||||
|
|
||||||
|
WebauthNTokenID string
|
||||||
|
|
||||||
|
State domain.WebAuthNState
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHumanWebAuthNWriteModel(userID, wbAuthNTokenID string) *HumanWebAuthNWriteModel {
|
||||||
|
return &HumanWebAuthNWriteModel{
|
||||||
|
WriteModel: eventstore.WriteModel{
|
||||||
|
AggregateID: userID,
|
||||||
|
},
|
||||||
|
WebauthNTokenID: wbAuthNTokenID,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *HumanWebAuthNWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||||
|
for _, event := range events {
|
||||||
|
switch e := event.(type) {
|
||||||
|
case *user.HumanWebAuthNAddedEvent:
|
||||||
|
if wm.WebauthNTokenID == e.WebAuthNTokenID {
|
||||||
|
wm.AppendEvents(e)
|
||||||
|
}
|
||||||
|
case *user.HumanWebAuthNRemovedEvent:
|
||||||
|
if wm.WebauthNTokenID == e.WebAuthNTokenID {
|
||||||
|
wm.AppendEvents(e)
|
||||||
|
}
|
||||||
|
case *user.UserRemovedEvent:
|
||||||
|
wm.AppendEvents(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *HumanWebAuthNWriteModel) Reduce() error {
|
||||||
|
for _, event := range wm.Events {
|
||||||
|
switch e := event.(type) {
|
||||||
|
case *user.HumanWebAuthNAddedEvent:
|
||||||
|
wm.WebauthNTokenID = e.WebAuthNTokenID
|
||||||
|
wm.State = domain.WebAuthNStateActive
|
||||||
|
case *user.HumanWebAuthNRemovedEvent:
|
||||||
|
wm.State = domain.WebAuthNStateRemoved
|
||||||
|
case *user.UserRemovedEvent:
|
||||||
|
wm.State = domain.WebAuthNStateRemoved
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return wm.WriteModel.Reduce()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *HumanWebAuthNWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||||
|
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, user.AggregateType).
|
||||||
|
AggregateIDs(wm.AggregateID)
|
||||||
|
}
|
@ -45,12 +45,12 @@ func (r *CommandSide) ChangeMachine(ctx context.Context, machine *domain.Machine
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if existingUser.UserState == domain.UserStateDeleted || existingUser.UserState == domain.UserStateUnspecified {
|
if existingUser.UserState == domain.UserStateDeleted || existingUser.UserState == domain.UserStateUnspecified {
|
||||||
return nil, caos_errs.ThrowAlreadyExists(nil, "COMMAND-5M0od", "Errors.User.NotFound")
|
return nil, caos_errs.ThrowNotFound(nil, "COMMAND-5M0od", "Errors.User.NotFound")
|
||||||
}
|
}
|
||||||
|
|
||||||
changedEvent, hasChanged := existingUser.NewChangedEvent(ctx, machine.Name, machine.Description)
|
changedEvent, hasChanged := existingUser.NewChangedEvent(ctx, machine.Name, machine.Description)
|
||||||
if !hasChanged {
|
if !hasChanged {
|
||||||
return nil, caos_errs.ThrowAlreadyExists(nil, "COMMAND-2M9fs", "Errors.User.Email.NotChanged")
|
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-2M9fs", "Errors.User.Email.NotChanged")
|
||||||
}
|
}
|
||||||
userAgg := UserAggregateFromWriteModel(&existingUser.WriteModel)
|
userAgg := UserAggregateFromWriteModel(&existingUser.WriteModel)
|
||||||
userAgg.PushEvents(changedEvent)
|
userAgg.PushEvents(changedEvent)
|
||||||
|
@ -30,6 +30,8 @@ func (wm *MachineWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
|||||||
switch e := event.(type) {
|
switch e := event.(type) {
|
||||||
case *user.MachineAddedEvent:
|
case *user.MachineAddedEvent:
|
||||||
wm.AppendEvents(e)
|
wm.AppendEvents(e)
|
||||||
|
case *user.UsernameChangedEvent:
|
||||||
|
wm.AppendEvents(e)
|
||||||
case *user.MachineChangedEvent:
|
case *user.MachineChangedEvent:
|
||||||
wm.AppendEvents(e)
|
wm.AppendEvents(e)
|
||||||
case *user.UserDeactivatedEvent:
|
case *user.UserDeactivatedEvent:
|
||||||
@ -55,6 +57,8 @@ func (wm *MachineWriteModel) Reduce() error {
|
|||||||
wm.Name = e.Name
|
wm.Name = e.Name
|
||||||
wm.Description = e.Description
|
wm.Description = e.Description
|
||||||
wm.UserState = domain.UserStateActive
|
wm.UserState = domain.UserStateActive
|
||||||
|
case *user.UsernameChangedEvent:
|
||||||
|
wm.UserName = e.UserName
|
||||||
case *user.MachineChangedEvent:
|
case *user.MachineChangedEvent:
|
||||||
if e.Name != nil {
|
if e.Name != nil {
|
||||||
wm.Name = *e.Name
|
wm.Name = *e.Name
|
@ -1,9 +1,11 @@
|
|||||||
package command
|
package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
caos_errors "github.com/caos/zitadel/internal/errors"
|
||||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||||
"github.com/caos/zitadel/internal/v2/domain"
|
"github.com/caos/zitadel/internal/v2/domain"
|
||||||
"github.com/caos/zitadel/internal/v2/repository/user"
|
"github.com/caos/zitadel/internal/v2/repository/user"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type UserWriteModel struct {
|
type UserWriteModel struct {
|
||||||
@ -24,14 +26,12 @@ func NewUserWriteModel(userID string) *UserWriteModel {
|
|||||||
func (wm *UserWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
func (wm *UserWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||||
for _, event := range events {
|
for _, event := range events {
|
||||||
switch e := event.(type) {
|
switch e := event.(type) {
|
||||||
case *user.HumanEmailChangedEvent:
|
|
||||||
wm.AppendEvents(e)
|
|
||||||
case *user.HumanEmailVerifiedEvent:
|
|
||||||
wm.AppendEvents(e)
|
|
||||||
case *user.HumanAddedEvent, *user.HumanRegisteredEvent:
|
case *user.HumanAddedEvent, *user.HumanRegisteredEvent:
|
||||||
wm.AppendEvents(e)
|
wm.AppendEvents(e)
|
||||||
case *user.MachineAddedEvent:
|
case *user.MachineAddedEvent:
|
||||||
wm.AppendEvents(e)
|
wm.AppendEvents(e)
|
||||||
|
case *user.UsernameChangedEvent:
|
||||||
|
wm.AppendEvents(e)
|
||||||
case *user.UserDeactivatedEvent:
|
case *user.UserDeactivatedEvent:
|
||||||
wm.AppendEvents(e)
|
wm.AppendEvents(e)
|
||||||
case *user.UserReactivatedEvent:
|
case *user.UserReactivatedEvent:
|
||||||
@ -56,10 +56,11 @@ func (wm *UserWriteModel) Reduce() error {
|
|||||||
case *user.HumanRegisteredEvent:
|
case *user.HumanRegisteredEvent:
|
||||||
wm.UserName = e.UserName
|
wm.UserName = e.UserName
|
||||||
wm.UserState = domain.UserStateInitial
|
wm.UserState = domain.UserStateInitial
|
||||||
|
|
||||||
case *user.MachineAddedEvent:
|
case *user.MachineAddedEvent:
|
||||||
wm.UserName = e.UserName
|
wm.UserName = e.UserName
|
||||||
wm.UserState = domain.UserStateActive
|
wm.UserState = domain.UserStateActive
|
||||||
|
case *user.UsernameChangedEvent:
|
||||||
|
wm.UserName = e.UserName
|
||||||
case *user.UserLockedEvent:
|
case *user.UserLockedEvent:
|
||||||
if wm.UserState != domain.UserStateDeleted {
|
if wm.UserState != domain.UserStateDeleted {
|
||||||
wm.UserState = domain.UserStateLocked
|
wm.UserState = domain.UserStateLocked
|
||||||
@ -93,3 +94,13 @@ func UserAggregateFromWriteModel(wm *eventstore.WriteModel) *user.Aggregate {
|
|||||||
Aggregate: *eventstore.AggregateFromWriteModel(wm, user.AggregateType, user.AggregateVersion),
|
Aggregate: *eventstore.AggregateFromWriteModel(wm, user.AggregateType, user.AggregateVersion),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CheckOrgIAMPolicyForUserName(userName string, policy *domain.OrgIAMPolicy) error {
|
||||||
|
if policy == nil {
|
||||||
|
return caos_errors.ThrowPreconditionFailed(nil, "COMMAND-3Mb9s", "Errors.Users.OrgIamPolicyNil")
|
||||||
|
}
|
||||||
|
if policy.UserLoginMustBeDomain && strings.Contains(userName, "@") {
|
||||||
|
return caos_errors.ThrowPreconditionFailed(nil, "COMMAND-4M9vs", "Errors.User.EmailAsUsernameNotAllowed")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -14,3 +14,17 @@ const (
|
|||||||
MultiFactorTypeUnspecified MultiFactorType = iota
|
MultiFactorTypeUnspecified MultiFactorType = iota
|
||||||
MultiFactorTypeU2FWithPIN
|
MultiFactorTypeU2FWithPIN
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type FactorState int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
FactorStateUnspecified FactorState = iota
|
||||||
|
FactorStateActive
|
||||||
|
FactorStateRemoved
|
||||||
|
|
||||||
|
factorStateCount
|
||||||
|
)
|
||||||
|
|
||||||
|
func (f FactorState) Valid() bool {
|
||||||
|
return f >= 0 && f < factorStateCount
|
||||||
|
}
|
||||||
|
@ -71,7 +71,8 @@ func (u *Human) SetNamesAsDisplayname() {
|
|||||||
|
|
||||||
func (u *Human) HashPasswordIfExisting(policy *PasswordComplexityPolicy, passwordAlg crypto.HashAlgorithm, onetime bool) error {
|
func (u *Human) HashPasswordIfExisting(policy *PasswordComplexityPolicy, passwordAlg crypto.HashAlgorithm, onetime bool) error {
|
||||||
if u.Password != nil {
|
if u.Password != nil {
|
||||||
return u.Password.HashPasswordIfExisting(policy, passwordAlg, onetime)
|
u.Password.ChangeRequired = onetime
|
||||||
|
return u.Password.HashPasswordIfExisting(policy, passwordAlg)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -11,3 +11,17 @@ type Address struct {
|
|||||||
Region string
|
Region string
|
||||||
StreetAddress string
|
StreetAddress string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AddressState int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
AddressStateUnspecified AddressState = iota
|
||||||
|
AddressStateActive
|
||||||
|
AddressStateRemoved
|
||||||
|
|
||||||
|
addressStateCount
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s AddressState) Valid() bool {
|
||||||
|
return s >= 0 && s < addressStateCount
|
||||||
|
}
|
||||||
|
@ -23,3 +23,14 @@ type EmailCode struct {
|
|||||||
func (e *Email) IsValid() bool {
|
func (e *Email) IsValid() bool {
|
||||||
return e.EmailAddress != ""
|
return e.EmailAddress != ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewEmailCode(emailGenerator crypto.Generator) (*EmailCode, error) {
|
||||||
|
emailCodeCrypto, _, err := crypto.NewCode(emailGenerator)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &EmailCode{
|
||||||
|
Code: emailCodeCrypto,
|
||||||
|
Expiry: emailGenerator.Expiry(),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
@ -5,7 +5,25 @@ import es_models "github.com/caos/zitadel/internal/eventstore/models"
|
|||||||
type ExternalIDP struct {
|
type ExternalIDP struct {
|
||||||
es_models.ObjectRoot
|
es_models.ObjectRoot
|
||||||
|
|
||||||
IDPConfigID string
|
IDPConfigID string
|
||||||
UserID string
|
ExternalUserID string
|
||||||
DisplayName string
|
DisplayName string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (idp *ExternalIDP) IsValid() bool {
|
||||||
|
return idp.AggregateID != "" && idp.IDPConfigID != "" && idp.ExternalUserID != ""
|
||||||
|
}
|
||||||
|
|
||||||
|
type ExternalIDPState int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
ExternalIDPStateUnspecified ExternalIDPState = iota
|
||||||
|
ExternalIDPStateActive
|
||||||
|
ExternalIDPStateRemoved
|
||||||
|
|
||||||
|
externalIDPStateCount
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s ExternalIDPState) Valid() bool {
|
||||||
|
return s >= 0 && s < externalIDPStateCount
|
||||||
}
|
}
|
||||||
|
@ -13,3 +13,17 @@ type OTP struct {
|
|||||||
Url string
|
Url string
|
||||||
State MFAState
|
State MFAState
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type OTPState int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
OTPStateUnspecified OTPState = iota
|
||||||
|
OTPStateActive
|
||||||
|
OTPStateRemoved
|
||||||
|
|
||||||
|
otpStateCount
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s OTPState) Valid() bool {
|
||||||
|
return s >= 0 && s < otpStateCount
|
||||||
|
}
|
||||||
|
@ -23,7 +23,7 @@ type PasswordCode struct {
|
|||||||
NotificationType NotificationType
|
NotificationType NotificationType
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Password) HashPasswordIfExisting(policy *PasswordComplexityPolicy, passwordAlg crypto.HashAlgorithm, onetime bool) error {
|
func (p *Password) HashPasswordIfExisting(policy *PasswordComplexityPolicy, passwordAlg crypto.HashAlgorithm) error {
|
||||||
if p.SecretString == "" {
|
if p.SecretString == "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -38,6 +38,16 @@ func (p *Password) HashPasswordIfExisting(policy *PasswordComplexityPolicy, pass
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
p.SecretCrypto = secret
|
p.SecretCrypto = secret
|
||||||
p.ChangeRequired = onetime
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewPasswordCode(passwordGenerator crypto.Generator) (*PasswordCode, error) {
|
||||||
|
passwordCodeCrypto, _, err := crypto.NewCode(passwordGenerator)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &PasswordCode{
|
||||||
|
Code: passwordCodeCrypto,
|
||||||
|
Expiry: passwordGenerator.Expiry(),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
@ -50,3 +50,17 @@ func NewPhoneCode(phoneGenerator crypto.Generator) (*PhoneCode, error) {
|
|||||||
Expiry: phoneGenerator.Expiry(),
|
Expiry: phoneGenerator.Expiry(),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PhoneState int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
PhoneStateUnspecified PhoneState = iota
|
||||||
|
PhoneStateActive
|
||||||
|
PhoneStateRemoved
|
||||||
|
|
||||||
|
phoneStateCount
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s PhoneState) Valid() bool {
|
||||||
|
return s >= 0 && s < phoneStateCount
|
||||||
|
}
|
||||||
|
@ -38,3 +38,17 @@ const (
|
|||||||
UserVerificationRequirementPreferred
|
UserVerificationRequirementPreferred
|
||||||
UserVerificationRequirementDiscouraged
|
UserVerificationRequirementDiscouraged
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type WebAuthNState int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
WebAuthNStateUnspecified WebAuthNState = iota
|
||||||
|
WebAuthNStateActive
|
||||||
|
WebAuthNStateRemoved
|
||||||
|
|
||||||
|
webAuthNStateCount
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s WebAuthNState) Valid() bool {
|
||||||
|
return s >= 0 && s < webAuthNStateCount
|
||||||
|
}
|
||||||
|
@ -14,3 +14,17 @@ type IAMMember struct {
|
|||||||
func (i *IAMMember) IsValid() bool {
|
func (i *IAMMember) IsValid() bool {
|
||||||
return i.AggregateID != "" && i.UserID != "" && len(i.Roles) != 0
|
return i.AggregateID != "" && i.UserID != "" && len(i.Roles) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type MemberState int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
MemberStateUnspecified MemberState = iota
|
||||||
|
MemberStateActive
|
||||||
|
MemberStateRemoved
|
||||||
|
|
||||||
|
memberStateCount
|
||||||
|
)
|
||||||
|
|
||||||
|
func (f MemberState) Valid() bool {
|
||||||
|
return f >= 0 && f < memberStateCount
|
||||||
|
}
|
||||||
|
15
internal/v2/domain/policy.go
Normal file
15
internal/v2/domain/policy.go
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package domain
|
||||||
|
|
||||||
|
type PolicyState int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
PolicyStateUnspecified PolicyState = iota
|
||||||
|
PolicyStateActive
|
||||||
|
PolicyStateRemoved
|
||||||
|
|
||||||
|
policyStateCount
|
||||||
|
)
|
||||||
|
|
||||||
|
func (f PolicyState) Valid() bool {
|
||||||
|
return f >= 0 && f < policyStateCount
|
||||||
|
}
|
@ -12,3 +12,17 @@ const (
|
|||||||
func (f IdentityProviderType) Valid() bool {
|
func (f IdentityProviderType) Valid() bool {
|
||||||
return f >= 0 && f < identityProviderCount
|
return f >= 0 && f < identityProviderCount
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type IdentityProviderState int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
IdentityProviderStateUnspecified IdentityProviderState = iota
|
||||||
|
IdentityProviderStateActive
|
||||||
|
IdentityProviderStateRemoved
|
||||||
|
|
||||||
|
idpProviderState
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s IdentityProviderState) Valid() bool {
|
||||||
|
return s >= 0 && s < idpProviderState
|
||||||
|
}
|
||||||
|
@ -61,6 +61,7 @@ type HumanExternalIDPAddedEvent struct {
|
|||||||
eventstore.BaseEvent `json:"-"`
|
eventstore.BaseEvent `json:"-"`
|
||||||
|
|
||||||
IDPConfigID string `json:"idpConfigId,omitempty"`
|
IDPConfigID string `json:"idpConfigId,omitempty"`
|
||||||
|
UserID string `json:"userId,omitempty"`
|
||||||
DisplayName string `json:"displayName,omitempty"`
|
DisplayName string `json:"displayName,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,19 +97,21 @@ type HumanExternalIDPRemovedEvent struct {
|
|||||||
eventstore.BaseEvent `json:"-"`
|
eventstore.BaseEvent `json:"-"`
|
||||||
|
|
||||||
IDPConfigID string `json:"idpConfigId"`
|
IDPConfigID string `json:"idpConfigId"`
|
||||||
|
UserID string `json:"userId,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *HumanExternalIDPRemovedEvent) Data() interface{} {
|
func (e *HumanExternalIDPRemovedEvent) Data() interface{} {
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHumanExternalIDPRemovedEvent(ctx context.Context, idpConfigID string) *HumanExternalIDPRemovedEvent {
|
func NewHumanExternalIDPRemovedEvent(ctx context.Context, idpConfigID, externalUserID string) *HumanExternalIDPRemovedEvent {
|
||||||
return &HumanExternalIDPRemovedEvent{
|
return &HumanExternalIDPRemovedEvent{
|
||||||
BaseEvent: *eventstore.NewBaseEventForPush(
|
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||||
ctx,
|
ctx,
|
||||||
HumanExternalIDPRemovedType,
|
HumanExternalIDPRemovedType,
|
||||||
),
|
),
|
||||||
IDPConfigID: idpConfigID,
|
IDPConfigID: idpConfigID,
|
||||||
|
UserID: externalUserID,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,19 +132,21 @@ type HumanExternalIDPCascadeRemovedEvent struct {
|
|||||||
eventstore.BaseEvent `json:"-"`
|
eventstore.BaseEvent `json:"-"`
|
||||||
|
|
||||||
IDPConfigID string `json:"idpConfigId"`
|
IDPConfigID string `json:"idpConfigId"`
|
||||||
|
UserID string `json:"userId,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *HumanExternalIDPCascadeRemovedEvent) Data() interface{} {
|
func (e *HumanExternalIDPCascadeRemovedEvent) Data() interface{} {
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHumanExternalIDPCascadeRemovedEvent(ctx context.Context, idpConfigID string) *HumanExternalIDPCascadeRemovedEvent {
|
func NewHumanExternalIDPCascadeRemovedEvent(ctx context.Context, idpConfigID, externalUserID string) *HumanExternalIDPCascadeRemovedEvent {
|
||||||
return &HumanExternalIDPCascadeRemovedEvent{
|
return &HumanExternalIDPCascadeRemovedEvent{
|
||||||
BaseEvent: *eventstore.NewBaseEventForPush(
|
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||||
ctx,
|
ctx,
|
||||||
HumanExternalIDPCascadeRemovedType,
|
HumanExternalIDPCascadeRemovedType,
|
||||||
),
|
),
|
||||||
IDPConfigID: idpConfigID,
|
IDPConfigID: idpConfigID,
|
||||||
|
UserID: externalUserID,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,6 @@ import (
|
|||||||
"github.com/caos/zitadel/internal/errors"
|
"github.com/caos/zitadel/internal/errors"
|
||||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||||
"github.com/caos/zitadel/internal/eventstore/v2/repository"
|
"github.com/caos/zitadel/internal/eventstore/v2/repository"
|
||||||
"github.com/caos/zitadel/internal/v2/domain"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -23,7 +22,6 @@ type HumanOTPAddedEvent struct {
|
|||||||
eventstore.BaseEvent `json:"-"`
|
eventstore.BaseEvent `json:"-"`
|
||||||
|
|
||||||
Secret *crypto.CryptoValue `json:"otpSecret,omitempty"`
|
Secret *crypto.CryptoValue `json:"otpSecret,omitempty"`
|
||||||
State domain.MFAState `json:"-"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *HumanOTPAddedEvent) Data() interface{} {
|
func (e *HumanOTPAddedEvent) Data() interface{} {
|
||||||
@ -44,7 +42,6 @@ func NewHumanOTPAddedEvent(ctx context.Context,
|
|||||||
func HumanOTPAddedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
|
func HumanOTPAddedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
|
||||||
otpAdded := &HumanOTPAddedEvent{
|
otpAdded := &HumanOTPAddedEvent{
|
||||||
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||||
State: domain.MFAStateNotReady,
|
|
||||||
}
|
}
|
||||||
err := json.Unmarshal(event.Data, otpAdded)
|
err := json.Unmarshal(event.Data, otpAdded)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -55,7 +52,6 @@ func HumanOTPAddedEventMapper(event *repository.Event) (eventstore.EventReader,
|
|||||||
|
|
||||||
type HumanOTPVerifiedEvent struct {
|
type HumanOTPVerifiedEvent struct {
|
||||||
eventstore.BaseEvent `json:"-"`
|
eventstore.BaseEvent `json:"-"`
|
||||||
State domain.MFAState `json:"-"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *HumanOTPVerifiedEvent) Data() interface{} {
|
func (e *HumanOTPVerifiedEvent) Data() interface{} {
|
||||||
@ -74,7 +70,6 @@ func NewHumanOTPVerifiedEvent(ctx context.Context) *HumanOTPVerifiedEvent {
|
|||||||
func HumanOTPVerifiedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
|
func HumanOTPVerifiedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
|
||||||
return &HumanOTPVerifiedEvent{
|
return &HumanOTPVerifiedEvent{
|
||||||
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||||
State: domain.MFAStateReady,
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ type HumanPasswordChangedEvent struct {
|
|||||||
|
|
||||||
Secret *crypto.CryptoValue `json:"secret,omitempty"`
|
Secret *crypto.CryptoValue `json:"secret,omitempty"`
|
||||||
ChangeRequired bool `json:"changeRequired"`
|
ChangeRequired bool `json:"changeRequired"`
|
||||||
|
UserAgentID string `json:"userAgentID,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *HumanPasswordChangedEvent) Data() interface{} {
|
func (e *HumanPasswordChangedEvent) Data() interface{} {
|
||||||
@ -35,6 +36,7 @@ func NewHumanPasswordChangedEvent(
|
|||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
secret *crypto.CryptoValue,
|
secret *crypto.CryptoValue,
|
||||||
changeRequired bool,
|
changeRequired bool,
|
||||||
|
userAgentID string,
|
||||||
) *HumanPasswordChangedEvent {
|
) *HumanPasswordChangedEvent {
|
||||||
return &HumanPasswordChangedEvent{
|
return &HumanPasswordChangedEvent{
|
||||||
BaseEvent: *eventstore.NewBaseEventForPush(
|
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||||
@ -43,6 +45,7 @@ func NewHumanPasswordChangedEvent(
|
|||||||
),
|
),
|
||||||
Secret: secret,
|
Secret: secret,
|
||||||
ChangeRequired: changeRequired,
|
ChangeRequired: changeRequired,
|
||||||
|
UserAgentID: userAgentID,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,13 +30,12 @@ func (e *HumanPhoneChangedEvent) Data() interface{} {
|
|||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHumanPhoneChangedEvent(ctx context.Context, phone string) *HumanPhoneChangedEvent {
|
func NewHumanPhoneChangedEvent(ctx context.Context) *HumanPhoneChangedEvent {
|
||||||
return &HumanPhoneChangedEvent{
|
return &HumanPhoneChangedEvent{
|
||||||
BaseEvent: *eventstore.NewBaseEventForPush(
|
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||||
ctx,
|
ctx,
|
||||||
HumanPhoneChangedType,
|
HumanPhoneChangedType,
|
||||||
),
|
),
|
||||||
PhoneNumber: phone,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user