mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-12 04:17:32 +00:00
feat: User login commands (#1228)
* feat: change login to command side * feat: change login to command side * fix: fix push on user * feat: user command side * feat: sign out * feat: command side login * feat: command side login * feat: fix register user * feat: fix register user * feat: fix web auth n events * feat: add machine keys * feat: send codes * feat: move authrequest to domain * feat: move authrequest to domain * feat: webauthn working * feat: external users * feat: external users login * feat: notify users * fix: tests * feat: cascade remove user grants on project remove * fix: webauthn * fix: pr requests * fix: register human with member * fix: fix bugs * fix: fix bugs
This commit is contained in:
@@ -36,14 +36,6 @@ func (repo *UserRepo) Health(ctx context.Context) error {
|
||||
return repo.UserEvents.Health(ctx)
|
||||
}
|
||||
|
||||
func (repo *UserRepo) Register(ctx context.Context, user *model.User, orgMember *org_model.OrgMember, resourceOwner string) (*model.User, error) {
|
||||
return repo.registerUser(ctx, user, nil, orgMember, resourceOwner)
|
||||
}
|
||||
|
||||
func (repo *UserRepo) RegisterExternalUser(ctx context.Context, user *model.User, externalIDP *model.ExternalIDP, orgMember *org_model.OrgMember, resourceOwner string) (*model.User, error) {
|
||||
return repo.registerUser(ctx, user, externalIDP, orgMember, resourceOwner)
|
||||
}
|
||||
|
||||
func (repo *UserRepo) registerUser(ctx context.Context, registerUser *model.User, externalIDP *model.ExternalIDP, orgMember *org_model.OrgMember, resourceOwner string) (*model.User, error) {
|
||||
policyResourceOwner := authz.GetCtxData(ctx).OrgID
|
||||
if resourceOwner != "" {
|
||||
@@ -133,18 +125,6 @@ func (repo *UserRepo) MyEmail(ctx context.Context) (*model.Email, error) {
|
||||
return user.GetEmail()
|
||||
}
|
||||
|
||||
func (repo *UserRepo) VerifyEmail(ctx context.Context, userID, code string) error {
|
||||
return repo.UserEvents.VerifyEmail(ctx, userID, code)
|
||||
}
|
||||
|
||||
func (repo *UserRepo) VerifyMyEmail(ctx context.Context, code string) error {
|
||||
return repo.UserEvents.VerifyEmail(ctx, authz.GetCtxData(ctx).UserID, code)
|
||||
}
|
||||
|
||||
func (repo *UserRepo) ResendEmailVerificationMail(ctx context.Context, userID string) error {
|
||||
return repo.UserEvents.CreateEmailVerificationCode(ctx, userID)
|
||||
}
|
||||
|
||||
func (repo *UserRepo) MyPhone(ctx context.Context) (*model.Phone, error) {
|
||||
user, err := repo.UserByID(ctx, authz.GetCtxData(ctx).UserID)
|
||||
if err != nil {
|
||||
@@ -156,21 +136,6 @@ func (repo *UserRepo) MyPhone(ctx context.Context) (*model.Phone, error) {
|
||||
return user.GetPhone()
|
||||
}
|
||||
|
||||
func (repo *UserRepo) ChangeMyPhone(ctx context.Context, phone *model.Phone) (*model.Phone, error) {
|
||||
if err := checkIDs(ctx, phone.ObjectRoot); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return repo.UserEvents.ChangePhone(ctx, phone)
|
||||
}
|
||||
|
||||
func (repo *UserRepo) RemoveMyPhone(ctx context.Context) error {
|
||||
return repo.UserEvents.RemovePhone(ctx, authz.GetCtxData(ctx).UserID)
|
||||
}
|
||||
|
||||
func (repo *UserRepo) VerifyMyPhone(ctx context.Context, code string) error {
|
||||
return repo.UserEvents.VerifyPhone(ctx, authz.GetCtxData(ctx).UserID, code)
|
||||
}
|
||||
|
||||
func (repo *UserRepo) MyAddress(ctx context.Context) (*model.Address, error) {
|
||||
user, err := repo.UserByID(ctx, authz.GetCtxData(ctx).UserID)
|
||||
if err != nil {
|
||||
@@ -182,34 +147,6 @@ func (repo *UserRepo) MyAddress(ctx context.Context) (*model.Address, error) {
|
||||
return user.GetAddress()
|
||||
}
|
||||
|
||||
func (repo *UserRepo) ChangeMyPassword(ctx context.Context, old, new string) error {
|
||||
policy, err := repo.View.PasswordComplexityPolicyByAggregateID(authz.GetCtxData(ctx).OrgID)
|
||||
if errors.IsNotFound(err) {
|
||||
policy, err = repo.View.PasswordComplexityPolicyByAggregateID(repo.SystemDefaults.IamID)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pwPolicyView := iam_es_model.PasswordComplexityViewToModel(policy)
|
||||
_, err = repo.UserEvents.ChangePassword(ctx, pwPolicyView, authz.GetCtxData(ctx).UserID, old, new, "")
|
||||
return err
|
||||
}
|
||||
|
||||
func (repo *UserRepo) ChangePassword(ctx context.Context, userID, old, new, userAgentID string) (err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
policy, err := repo.View.PasswordComplexityPolicyByAggregateID(authz.GetCtxData(ctx).OrgID)
|
||||
if errors.IsNotFound(err) {
|
||||
policy, err = repo.View.PasswordComplexityPolicyByAggregateID(repo.SystemDefaults.IamID)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pwPolicyView := iam_es_model.PasswordComplexityViewToModel(policy)
|
||||
_, err = repo.UserEvents.ChangePassword(ctx, pwPolicyView, userID, old, new, userAgentID)
|
||||
return err
|
||||
}
|
||||
|
||||
func (repo *UserRepo) MyUserMFAs(ctx context.Context) ([]*model.MultiFactor, error) {
|
||||
user, err := repo.UserByID(ctx, authz.GetCtxData(ctx).UserID)
|
||||
if err != nil {
|
||||
@@ -225,142 +162,24 @@ func (repo *UserRepo) MyUserMFAs(ctx context.Context) ([]*model.MultiFactor, err
|
||||
return mfas, nil
|
||||
}
|
||||
|
||||
func (repo *UserRepo) AddMFAOTP(ctx context.Context, userID string) (*model.OTP, error) {
|
||||
accountName := ""
|
||||
user, err := repo.UserByID(ctx, userID)
|
||||
if err != nil {
|
||||
logging.Log("EVENT-Fk93s").WithError(err).WithField("traceID", tracing.TraceIDFromCtx(ctx)).Debug("unable to get user for loginname")
|
||||
} else {
|
||||
accountName = user.PreferredLoginName
|
||||
}
|
||||
return repo.UserEvents.AddOTP(ctx, userID, accountName)
|
||||
}
|
||||
|
||||
func (repo *UserRepo) VerifyMFAOTPSetup(ctx context.Context, userID, code, userAgentID string) error {
|
||||
return repo.UserEvents.CheckMFAOTPSetup(ctx, userID, code, userAgentID)
|
||||
}
|
||||
|
||||
func (repo *UserRepo) RemoveMyMFAOTP(ctx context.Context) error {
|
||||
return repo.UserEvents.RemoveOTP(ctx, authz.GetCtxData(ctx).UserID)
|
||||
}
|
||||
|
||||
func (repo *UserRepo) AddMFAU2F(ctx context.Context, userID string) (*model.WebAuthNToken, error) {
|
||||
accountName := ""
|
||||
user, err := repo.UserByID(ctx, userID)
|
||||
if err != nil {
|
||||
logging.Log("EVENT-DAqe1").WithError(err).WithField("traceID", tracing.TraceIDFromCtx(ctx)).Debug("unable to get user for loginname")
|
||||
} else {
|
||||
accountName = user.PreferredLoginName
|
||||
}
|
||||
return repo.UserEvents.AddU2F(ctx, userID, accountName, true)
|
||||
}
|
||||
|
||||
func (repo *UserRepo) AddMyMFAU2F(ctx context.Context) (*model.WebAuthNToken, error) {
|
||||
userID := authz.GetCtxData(ctx).UserID
|
||||
accountName := ""
|
||||
user, err := repo.UserByID(ctx, userID)
|
||||
if err != nil {
|
||||
logging.Log("EVENT-Ghwl1").WithError(err).WithField("traceID", tracing.TraceIDFromCtx(ctx)).Debug("unable to get user for loginname")
|
||||
} else {
|
||||
accountName = user.PreferredLoginName
|
||||
}
|
||||
return repo.UserEvents.AddU2F(ctx, userID, accountName, false)
|
||||
}
|
||||
|
||||
func (repo *UserRepo) VerifyMFAU2FSetup(ctx context.Context, userID, tokenName, userAgentID string, credentialData []byte) error {
|
||||
return repo.UserEvents.VerifyU2FSetup(ctx, userID, tokenName, userAgentID, credentialData)
|
||||
}
|
||||
|
||||
func (repo *UserRepo) GetPasswordless(ctx context.Context, userID string) ([]*model.WebAuthNToken, error) {
|
||||
return repo.UserEvents.GetPasswordless(ctx, userID)
|
||||
}
|
||||
|
||||
func (repo *UserRepo) AddPasswordless(ctx context.Context, userID string) (*model.WebAuthNToken, error) {
|
||||
accountName := ""
|
||||
user, err := repo.UserByID(ctx, userID)
|
||||
if err != nil {
|
||||
logging.Log("EVENT-Vj2k1").WithError(err).WithField("traceID", tracing.TraceIDFromCtx(ctx)).Debug("unable to get user for loginname")
|
||||
} else {
|
||||
accountName = user.PreferredLoginName
|
||||
}
|
||||
return repo.UserEvents.AddPasswordless(ctx, userID, accountName, true)
|
||||
}
|
||||
|
||||
func (repo *UserRepo) GetMyPasswordless(ctx context.Context) ([]*model.WebAuthNToken, error) {
|
||||
return repo.UserEvents.GetPasswordless(ctx, authz.GetCtxData(ctx).UserID)
|
||||
}
|
||||
|
||||
func (repo *UserRepo) VerifyPasswordlessSetup(ctx context.Context, userID, tokenName, userAgentID string, credentialData []byte) error {
|
||||
return repo.UserEvents.VerifyPasswordlessSetup(ctx, userID, tokenName, userAgentID, credentialData)
|
||||
}
|
||||
|
||||
func (repo *UserRepo) RemoveMyPasswordless(ctx context.Context, webAuthNTokenID string) error {
|
||||
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 {
|
||||
_, err := repo.UserEvents.CreateInitializeUserCodeByID(ctx, userID)
|
||||
return err
|
||||
}
|
||||
|
||||
func (repo *UserRepo) VerifyInitCode(ctx context.Context, userID, code, password string) error {
|
||||
policy, err := repo.View.PasswordComplexityPolicyByAggregateID(authz.GetCtxData(ctx).OrgID)
|
||||
if errors.IsNotFound(err) {
|
||||
policy, err = repo.View.PasswordComplexityPolicyByAggregateID(repo.SystemDefaults.IamID)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pwPolicyView := iam_es_model.PasswordComplexityViewToModel(policy)
|
||||
return repo.UserEvents.VerifyInitCode(ctx, pwPolicyView, userID, code, password)
|
||||
}
|
||||
|
||||
func (repo *UserRepo) SkipMFAInit(ctx context.Context, userID string) error {
|
||||
return repo.UserEvents.SkipMFAInit(ctx, userID)
|
||||
}
|
||||
|
||||
func (repo *UserRepo) RequestPasswordReset(ctx context.Context, loginname string) error {
|
||||
user, err := repo.View.UserByLoginName(loginname)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return repo.UserEvents.RequestSetPassword(ctx, user.ID, model.NotificationTypeEmail)
|
||||
}
|
||||
|
||||
func (repo *UserRepo) SetPassword(ctx context.Context, userID, code, password, userAgentID string) error {
|
||||
policy, err := repo.View.PasswordComplexityPolicyByAggregateID(authz.GetCtxData(ctx).OrgID)
|
||||
if errors.IsNotFound(err) {
|
||||
policy, err = repo.View.PasswordComplexityPolicyByAggregateID(repo.SystemDefaults.IamID)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pwPolicyView := iam_es_model.PasswordComplexityViewToModel(policy)
|
||||
return repo.UserEvents.SetPassword(ctx, pwPolicyView, userID, code, password, userAgentID)
|
||||
}
|
||||
|
||||
func (repo *UserRepo) SignOut(ctx context.Context, agentID string) error {
|
||||
func (repo *UserRepo) UserSessionUserIDsByAgentID(ctx context.Context, agentID string) ([]string, error) {
|
||||
userSessions, err := repo.View.UserSessionsByAgentID(agentID)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
userIDs := make([]string, len(userSessions))
|
||||
for i, session := range userSessions {
|
||||
userIDs[i] = session.UserID
|
||||
}
|
||||
return repo.UserEvents.SignOut(ctx, agentID, userIDs)
|
||||
return userIDs, nil
|
||||
}
|
||||
|
||||
func (repo *UserRepo) UserByID(ctx context.Context, id string) (*model.UserView, error) {
|
||||
@@ -385,6 +204,27 @@ func (repo *UserRepo) UserByID(ctx context.Context, id string) (*model.UserView,
|
||||
return usr_view_model.UserToModel(&userCopy), nil
|
||||
}
|
||||
|
||||
func (repo *UserRepo) UserByLoginName(ctx context.Context, loginname string) (*model.UserView, error) {
|
||||
user, err := repo.View.UserByLoginName(loginname)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
events, err := repo.UserEvents.UserEventsByID(ctx, user.ID, user.Sequence)
|
||||
if err != nil {
|
||||
logging.Log("EVENT-PSoc3").WithError(err).WithField("traceID", tracing.TraceIDFromCtx(ctx)).Debug("error retrieving new events")
|
||||
return usr_view_model.UserToModel(user), nil
|
||||
}
|
||||
userCopy := *user
|
||||
for _, event := range events {
|
||||
if err := userCopy.AppendEvent(event); err != nil {
|
||||
return usr_view_model.UserToModel(user), nil
|
||||
}
|
||||
}
|
||||
if userCopy.State == int32(model.UserStateDeleted) {
|
||||
return nil, errors.ThrowNotFound(nil, "EVENT-vZ8us", "Errors.User.NotFound")
|
||||
}
|
||||
return usr_view_model.UserToModel(&userCopy), nil
|
||||
}
|
||||
func (repo *UserRepo) MyUserChanges(ctx context.Context, lastSequence uint64, limit uint64, sortAscending bool) (*model.UserChanges, error) {
|
||||
changes, err := repo.UserEvents.UserChanges(ctx, authz.GetCtxData(ctx).UserID, lastSequence, limit, sortAscending)
|
||||
if err != nil {
|
||||
@@ -405,19 +245,6 @@ func (repo *UserRepo) MyUserChanges(ctx context.Context, lastSequence uint64, li
|
||||
return changes, nil
|
||||
}
|
||||
|
||||
func (repo *UserRepo) ChangeUsername(ctx context.Context, userID, username string) error {
|
||||
policyResourceOwner := authz.GetCtxData(ctx).OrgID
|
||||
orgPolicy, err := repo.View.OrgIAMPolicyByAggregateID(policyResourceOwner)
|
||||
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, userID, username, orgPolicyView)
|
||||
}
|
||||
|
||||
func checkIDs(ctx context.Context, obj es_models.ObjectRoot) error {
|
||||
if obj.AggregateID != authz.GetCtxData(ctx).UserID {
|
||||
return errors.ThrowPermissionDenied(nil, "EVENT-kFi9w", "object does not belong to user")
|
||||
|
Reference in New Issue
Block a user