mirror of
https://github.com/zitadel/zitadel.git
synced 2025-04-28 12:20:50 +00:00
fix: add authenticators to user v3 endpoints
This commit is contained in:
parent
ee5de6563a
commit
418771b466
@ -24,14 +24,38 @@ func (s *Server) SetPassword(ctx context.Context, req *user.SetPasswordRequest)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func setPasswordRequestToSetSchemaUserPassword(req *user.SetPasswordRequest) *command.SetSchemaUserPassword {
|
func setPasswordRequestToSetSchemaUserPassword(req *user.SetPasswordRequest) *command.SetSchemaUserPassword {
|
||||||
|
pw, verification := setPasswordToSetSchemaUserPassword(req.GetNewPassword())
|
||||||
return &command.SetSchemaUserPassword{
|
return &command.SetSchemaUserPassword{
|
||||||
ResourceOwner: organizationToUpdateResourceOwner(req.Organization),
|
ResourceOwner: organizationToUpdateResourceOwner(req.Organization),
|
||||||
UserID: req.GetId(),
|
UserID: req.GetId(),
|
||||||
Password: req.GetNewPassword().GetPassword(),
|
Password: pw,
|
||||||
EncodedPasswordHash: req.GetNewPassword().GetHash(),
|
Verification: verification,
|
||||||
ChangeRequired: req.GetNewPassword().GetChangeRequired(),
|
}
|
||||||
VerificationCode: req.GetNewPassword().GetVerificationCode(),
|
}
|
||||||
CurrentPassword: req.GetNewPassword().GetCurrentPassword(),
|
|
||||||
|
func setPasswordToSetSchemaUserPassword(req *user.SetPassword) (*command.SchemaUserPassword, *command.SchemaUserPasswordVerification) {
|
||||||
|
return setPasswordToSchemaUserPassword(req.GetPassword(), req.GetHash(), req.GetChangeRequired()),
|
||||||
|
setPasswordToSchemaUserPasswordVerification(req.GetCurrentPassword(), req.GetVerificationCode())
|
||||||
|
}
|
||||||
|
|
||||||
|
func setPasswordToSchemaUserPassword(pw string, hash string, changeRequired bool) *command.SchemaUserPassword {
|
||||||
|
if pw == "" && hash == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &command.SchemaUserPassword{
|
||||||
|
Password: pw,
|
||||||
|
EncodedPasswordHash: hash,
|
||||||
|
ChangeRequired: changeRequired,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setPasswordToSchemaUserPasswordVerification(pw string, code string) *command.SchemaUserPasswordVerification {
|
||||||
|
if pw == "" && code == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &command.SchemaUserPasswordVerification{
|
||||||
|
CurrentPassword: pw,
|
||||||
|
Code: code,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,21 +25,32 @@ func (s *Server) AddPersonalAccessToken(ctx context.Context, req *user.AddPerson
|
|||||||
return &user.AddPersonalAccessTokenResponse{
|
return &user.AddPersonalAccessTokenResponse{
|
||||||
Details: resource_object.DomainToDetailsPb(details, object.OwnerType_OWNER_TYPE_ORG, details.ResourceOwner),
|
Details: resource_object.DomainToDetailsPb(details, object.OwnerType_OWNER_TYPE_ORG, details.ResourceOwner),
|
||||||
PersonalAccessTokenId: details.ID,
|
PersonalAccessTokenId: details.ID,
|
||||||
PersonalAccessToken: pat.Token,
|
PersonalAccessToken: pat.PAT.Token,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func addPersonalAccessTokenRequestToAddPAT(req *user.AddPersonalAccessTokenRequest) *command.AddPAT {
|
func addPersonalAccessTokenRequestToAddPAT(req *user.AddPersonalAccessTokenRequest) *command.AddPAT {
|
||||||
expDate := time.Time{}
|
if req == nil {
|
||||||
if req.GetPersonalAccessToken().GetExpirationDate() != nil {
|
return nil
|
||||||
expDate = req.GetPersonalAccessToken().GetExpirationDate().AsTime()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &command.AddPAT{
|
return &command.AddPAT{
|
||||||
ResourceOwner: organizationToUpdateResourceOwner(req.Organization),
|
ResourceOwner: organizationToUpdateResourceOwner(req.Organization),
|
||||||
UserID: req.GetId(),
|
UserID: req.GetId(),
|
||||||
|
PAT: setPersonalAccessTokenToAddPAT(req.GetPersonalAccessToken()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setPersonalAccessTokenToAddPAT(set *user.SetPersonalAccessToken) *command.PAT {
|
||||||
|
if set == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
expDate := time.Time{}
|
||||||
|
if set.GetExpirationDate() != nil {
|
||||||
|
expDate = set.GetExpirationDate().AsTime()
|
||||||
|
}
|
||||||
|
return &command.PAT{
|
||||||
ExpirationDate: expDate,
|
ExpirationDate: expDate,
|
||||||
Scope: []string{oidc.ScopeOpenID, oidc.ScopeProfile, z_oidc.ScopeUserMetaData, z_oidc.ScopeResourceOwner},
|
Scopes: []string{oidc.ScopeOpenID, oidc.ScopeProfile, z_oidc.ScopeUserMetaData, z_oidc.ScopeResourceOwner},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,19 +22,31 @@ func (s *Server) AddPublicKey(ctx context.Context, req *user.AddPublicKeyRequest
|
|||||||
return &user.AddPublicKeyResponse{
|
return &user.AddPublicKeyResponse{
|
||||||
Details: resource_object.DomainToDetailsPb(details, object.OwnerType_OWNER_TYPE_ORG, details.ResourceOwner),
|
Details: resource_object.DomainToDetailsPb(details, object.OwnerType_OWNER_TYPE_ORG, details.ResourceOwner),
|
||||||
PublicKeyId: details.ID,
|
PublicKeyId: details.ID,
|
||||||
PrivateKey: pk.PrivateKey,
|
PrivateKey: pk.GetPrivateKey(),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func addPublicKeyRequestToAddPublicKey(req *user.AddPublicKeyRequest) *command.AddPublicKey {
|
func addPublicKeyRequestToAddPublicKey(req *user.AddPublicKeyRequest) *command.AddPublicKey {
|
||||||
expDate := time.Time{}
|
if req == nil {
|
||||||
if req.GetPublicKey().GetExpirationDate() != nil {
|
return nil
|
||||||
expDate = req.GetPublicKey().GetExpirationDate().AsTime()
|
|
||||||
}
|
}
|
||||||
return &command.AddPublicKey{
|
return &command.AddPublicKey{
|
||||||
ResourceOwner: organizationToUpdateResourceOwner(req.Organization),
|
ResourceOwner: organizationToUpdateResourceOwner(req.Organization),
|
||||||
UserID: req.GetId(),
|
UserID: req.GetId(),
|
||||||
PublicKey: req.GetPublicKey().GetPublicKey().GetPublicKey(),
|
PublicKey: setPublicKeyToAddPublicKey(req.GetPublicKey()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setPublicKeyToAddPublicKey(req *user.SetPublicKey) *command.PublicKey {
|
||||||
|
if req == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
expDate := time.Time{}
|
||||||
|
if req.GetExpirationDate() != nil {
|
||||||
|
expDate = req.GetExpirationDate().AsTime()
|
||||||
|
}
|
||||||
|
return &command.PublicKey{
|
||||||
|
PublicKey: req.GetPublicKey().GetPublicKey(),
|
||||||
ExpirationDate: expDate,
|
ExpirationDate: expDate,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,20 +30,54 @@ func (s *Server) CreateUser(ctx context.Context, req *user.CreateUserRequest) (_
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type authenticators struct {
|
||||||
|
Usernames []*command.Username
|
||||||
|
Password *command.SchemaUserPassword
|
||||||
|
PublicKeys []*command.PublicKey
|
||||||
|
PATs []*command.PAT
|
||||||
|
}
|
||||||
|
|
||||||
|
func setAuthenticatorsToAuthenticators(set *user.SetAuthenticators) *authenticators {
|
||||||
|
if set == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
auths := &authenticators{}
|
||||||
|
for _, u := range set.GetUsernames() {
|
||||||
|
auths.Usernames = append(auths.Usernames, setUsernameToAddUsername(u))
|
||||||
|
}
|
||||||
|
if set.GetPassword() != nil {
|
||||||
|
auths.Password = setPasswordToSchemaUserPassword(set.GetPassword().GetPassword(), set.GetPassword().GetHash(), set.GetPassword().GetChangeRequired())
|
||||||
|
}
|
||||||
|
for _, p := range set.GetPublicKey() {
|
||||||
|
auths.PublicKeys = append(auths.PublicKeys, setPublicKeyToAddPublicKey(p))
|
||||||
|
}
|
||||||
|
for _, p := range set.GetPersonalAccessToken() {
|
||||||
|
auths.PATs = append(auths.PATs, setPersonalAccessTokenToAddPAT(p))
|
||||||
|
}
|
||||||
|
return auths
|
||||||
|
}
|
||||||
|
|
||||||
func createUserRequestToCreateSchemaUser(ctx context.Context, req *user.CreateUserRequest) (*command.CreateSchemaUser, error) {
|
func createUserRequestToCreateSchemaUser(ctx context.Context, req *user.CreateUserRequest) (*command.CreateSchemaUser, error) {
|
||||||
data, err := req.GetUser().GetData().MarshalJSON()
|
data, err := req.GetUser().GetData().MarshalJSON()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &command.CreateSchemaUser{
|
user := &command.CreateSchemaUser{
|
||||||
ResourceOwner: organizationToCreateResourceOwner(ctx, req.Organization),
|
ResourceOwner: organizationToCreateResourceOwner(ctx, req.Organization),
|
||||||
SchemaID: req.GetUser().GetSchemaId(),
|
SchemaID: req.GetUser().GetSchemaId(),
|
||||||
ID: req.GetUser().GetUserId(),
|
ID: req.GetUser().GetUserId(),
|
||||||
Data: data,
|
Data: data,
|
||||||
Email: setEmailToEmail(req.GetUser().GetContact().GetEmail()),
|
Email: setEmailToEmail(req.GetUser().GetContact().GetEmail()),
|
||||||
Phone: setPhoneToPhone(req.GetUser().GetContact().GetPhone()),
|
Phone: setPhoneToPhone(req.GetUser().GetContact().GetPhone()),
|
||||||
}, nil
|
}
|
||||||
|
if auths := setAuthenticatorsToAuthenticators(req.GetUser().Authenticators); auths != nil {
|
||||||
|
user.Usernames = auths.Usernames
|
||||||
|
user.Password = auths.Password
|
||||||
|
user.PublicKeys = auths.PublicKeys
|
||||||
|
user.PATs = auths.PATs
|
||||||
|
}
|
||||||
|
return user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func organizationToCreateResourceOwner(ctx context.Context, org *object.Organization) string {
|
func organizationToCreateResourceOwner(ctx context.Context, org *object.Organization) string {
|
||||||
|
@ -24,11 +24,23 @@ func (s *Server) AddUsername(ctx context.Context, req *user.AddUsernameRequest)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func addUsernameRequestToAddUsername(req *user.AddUsernameRequest) *command.AddUsername {
|
func addUsernameRequestToAddUsername(req *user.AddUsernameRequest) *command.AddUsername {
|
||||||
|
if req == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return &command.AddUsername{
|
return &command.AddUsername{
|
||||||
ResourceOwner: organizationToUpdateResourceOwner(req.Organization),
|
ResourceOwner: organizationToUpdateResourceOwner(req.Organization),
|
||||||
UserID: req.GetId(),
|
UserID: req.GetId(),
|
||||||
Username: req.GetUsername().GetUsername(),
|
Username: setUsernameToAddUsername(req.GetUsername()),
|
||||||
IsOrgSpecific: req.GetUsername().GetIsOrganizationSpecific(),
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setUsernameToAddUsername(req *user.SetUsername) *command.Username {
|
||||||
|
if req == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &command.Username{
|
||||||
|
Username: req.GetUsername(),
|
||||||
|
IsOrgSpecific: req.GetIsOrganizationSpecific(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,11 @@ type CreateSchemaUser struct {
|
|||||||
ReturnCodeEmail *string
|
ReturnCodeEmail *string
|
||||||
Phone *Phone
|
Phone *Phone
|
||||||
ReturnCodePhone *string
|
ReturnCodePhone *string
|
||||||
|
|
||||||
|
Usernames []*Username
|
||||||
|
Password *SchemaUserPassword
|
||||||
|
PublicKeys []*PublicKey
|
||||||
|
PATs []*PAT
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *CreateSchemaUser) Valid() (err error) {
|
func (s *CreateSchemaUser) Valid() (err error) {
|
||||||
@ -84,6 +89,34 @@ func (c *Commands) CreateSchemaUser(ctx context.Context, user *CreateSchemaUser)
|
|||||||
if codePhone != "" {
|
if codePhone != "" {
|
||||||
user.ReturnCodePhone = &codePhone
|
user.ReturnCodePhone = &codePhone
|
||||||
}
|
}
|
||||||
|
for i := range user.Usernames {
|
||||||
|
_, usernameEvents, err := c.addUsername(ctx, writeModel.ResourceOwner, writeModel.AggregateID, user.Usernames[i])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
events = append(events, usernameEvents...)
|
||||||
|
}
|
||||||
|
if user.Password != nil {
|
||||||
|
_, pwEvents, err := c.setSchemaUserPassword(ctx, writeModel.ResourceOwner, writeModel.AggregateID, nil, user.Password)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
events = append(events, pwEvents...)
|
||||||
|
}
|
||||||
|
for i := range user.PublicKeys {
|
||||||
|
_, pkEvents, err := c.addPublicKey(ctx, writeModel.ResourceOwner, writeModel.AggregateID, user.PublicKeys[i])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
events = append(events, pkEvents...)
|
||||||
|
}
|
||||||
|
for i := range user.PATs {
|
||||||
|
_, patEvents, err := c.addPAT(ctx, writeModel.ResourceOwner, writeModel.AggregateID, user.PATs[i])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
events = append(events, patEvents...)
|
||||||
|
}
|
||||||
return c.pushAppendAndReduceDetails(ctx, writeModel, events...)
|
return c.pushAppendAndReduceDetails(ctx, writeModel, events...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/zitadel/zitadel/internal/crypto"
|
"github.com/zitadel/zitadel/internal/crypto"
|
||||||
"github.com/zitadel/zitadel/internal/domain"
|
"github.com/zitadel/zitadel/internal/domain"
|
||||||
|
"github.com/zitadel/zitadel/internal/eventstore"
|
||||||
"github.com/zitadel/zitadel/internal/telemetry/tracing"
|
"github.com/zitadel/zitadel/internal/telemetry/tracing"
|
||||||
"github.com/zitadel/zitadel/internal/zerrors"
|
"github.com/zitadel/zitadel/internal/zerrors"
|
||||||
)
|
)
|
||||||
@ -14,19 +15,22 @@ type SetSchemaUserPassword struct {
|
|||||||
ResourceOwner string
|
ResourceOwner string
|
||||||
UserID string
|
UserID string
|
||||||
|
|
||||||
|
Verification *SchemaUserPasswordVerification
|
||||||
|
Password *SchemaUserPassword
|
||||||
|
}
|
||||||
|
|
||||||
|
type SchemaUserPasswordVerification struct {
|
||||||
|
CurrentPassword string
|
||||||
|
Code string
|
||||||
|
}
|
||||||
|
|
||||||
|
type SchemaUserPassword struct {
|
||||||
Password string
|
Password string
|
||||||
EncodedPasswordHash string
|
EncodedPasswordHash string
|
||||||
ChangeRequired bool
|
ChangeRequired bool
|
||||||
|
|
||||||
CurrentPassword string
|
|
||||||
VerificationCode string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *SetSchemaUserPassword) Validate(hasher *crypto.Hasher) (err error) {
|
func (p *SchemaUserPassword) Validate(hasher *crypto.Hasher) (err error) {
|
||||||
if p.UserID == "" {
|
|
||||||
return zerrors.ThrowInvalidArgument(nil, "COMMAND-aS3Vz5t6BS", "Errors.IDMissing")
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.EncodedPasswordHash != "" {
|
if p.EncodedPasswordHash != "" {
|
||||||
if !hasher.EncodingSupported(p.EncodedPasswordHash) {
|
if !hasher.EncodingSupported(p.EncodedPasswordHash) {
|
||||||
return zerrors.ThrowInvalidArgument(nil, "COMMAND-oz74onzvqr", "Errors.User.Password.NotSupported")
|
return zerrors.ThrowInvalidArgument(nil, "COMMAND-oz74onzvqr", "Errors.User.Password.NotSupported")
|
||||||
@ -35,56 +39,75 @@ func (p *SetSchemaUserPassword) Validate(hasher *crypto.Hasher) (err error) {
|
|||||||
if p.Password == "" && p.EncodedPasswordHash == "" {
|
if p.Password == "" && p.EncodedPasswordHash == "" {
|
||||||
return zerrors.ThrowInvalidArgument(nil, "COMMAND-3klek4sbns", "Errors.User.Password.Empty")
|
return zerrors.ThrowInvalidArgument(nil, "COMMAND-3klek4sbns", "Errors.User.Password.Empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Commands) SetSchemaUserPassword(ctx context.Context, user *SetSchemaUserPassword) (*domain.ObjectDetails, error) {
|
func (c *Commands) SetSchemaUserPassword(ctx context.Context, set *SetSchemaUserPassword) (*domain.ObjectDetails, error) {
|
||||||
if err := user.Validate(c.userPasswordHasher); err != nil {
|
if set.UserID == "" {
|
||||||
|
return nil, zerrors.ThrowInvalidArgument(nil, "COMMAND-aS3Vz5t6BS", "Errors.IDMissing")
|
||||||
|
}
|
||||||
|
if err := set.Password.Validate(c.userPasswordHasher); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
schemauser, err := existingSchemaUser(ctx, c, set.ResourceOwner, set.UserID)
|
||||||
schemaUser := &schemaUserPassword{
|
|
||||||
Create: true,
|
|
||||||
ResourceOwner: user.ResourceOwner,
|
|
||||||
UserID: user.UserID,
|
|
||||||
VerificationCode: user.VerificationCode,
|
|
||||||
CurrentPassword: user.CurrentPassword,
|
|
||||||
Password: user.Password,
|
|
||||||
EncodedPasswordHash: user.EncodedPasswordHash,
|
|
||||||
}
|
|
||||||
|
|
||||||
writeModel, err := c.getSchemaUserPasswordWithVerification(ctx, schemaUser)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
set.ResourceOwner = schemauser.ResourceOwner
|
||||||
|
|
||||||
// If password is provided, let's check if is compliant with the policy.
|
_, err = existingSchema(ctx, c, "", schemauser.SchemaID)
|
||||||
// If only a encodedPassword is passed, we can skip this.
|
if err != nil {
|
||||||
if user.Password != "" {
|
|
||||||
if err = c.checkPasswordComplexity(ctx, user.Password, writeModel.ResourceOwner); err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
// TODO check for possible authenticators
|
||||||
|
|
||||||
encodedPassword := schemaUser.EncodedPasswordHash
|
writeModel, events, err := c.setSchemaUserPassword(ctx, set.ResourceOwner, set.UserID, set.Verification, set.Password)
|
||||||
if encodedPassword == "" && user.Password != "" {
|
|
||||||
encodedPassword, err = c.userPasswordHasher.Hash(user.Password)
|
|
||||||
if err = convertPasswapErr(err); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
events, err := writeModel.NewCreate(ctx,
|
|
||||||
encodedPassword,
|
|
||||||
user.ChangeRequired,
|
|
||||||
)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return c.pushAppendAndReduceDetails(ctx, writeModel, events...)
|
return c.pushAppendAndReduceDetails(ctx, writeModel, events...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Commands) setSchemaUserPassword(ctx context.Context, resourceOwner, userID string, verification *SchemaUserPasswordVerification, set *SchemaUserPassword) (*PasswordV3WriteModel, []eventstore.Command, error) {
|
||||||
|
if set == nil {
|
||||||
|
return nil, nil, nil
|
||||||
|
}
|
||||||
|
schemaUser := &schemaUserPassword{
|
||||||
|
Set: true,
|
||||||
|
ResourceOwner: resourceOwner,
|
||||||
|
UserID: userID,
|
||||||
|
Verification: verification,
|
||||||
|
NewPassword: set,
|
||||||
|
}
|
||||||
|
writeModel, err := c.getSchemaUserPasswordWithVerification(ctx, schemaUser)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// If password is provided, let's check if is compliant with the policy.
|
||||||
|
// If only a encodedPassword is passed, we can skip this.
|
||||||
|
if set.Password != "" {
|
||||||
|
if err = c.checkPasswordComplexity(ctx, set.Password, writeModel.ResourceOwner); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
encodedPassword := schemaUser.NewPassword.EncodedPasswordHash
|
||||||
|
if encodedPassword == "" && set.Password != "" {
|
||||||
|
encodedPassword, err = c.userPasswordHasher.Hash(set.Password)
|
||||||
|
if err = convertPasswapErr(err); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
events, err := writeModel.NewCreate(ctx,
|
||||||
|
encodedPassword,
|
||||||
|
set.ChangeRequired,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return writeModel, events, nil
|
||||||
|
}
|
||||||
|
|
||||||
type RequestSchemaUserPasswordReset struct {
|
type RequestSchemaUserPasswordReset struct {
|
||||||
ResourceOwner string
|
ResourceOwner string
|
||||||
UserID string
|
UserID string
|
||||||
@ -132,13 +155,11 @@ func (c *Commands) DeleteSchemaUserPassword(ctx context.Context, resourceOwner,
|
|||||||
}
|
}
|
||||||
|
|
||||||
type schemaUserPassword struct {
|
type schemaUserPassword struct {
|
||||||
Create bool
|
Set bool
|
||||||
ResourceOwner string
|
ResourceOwner string
|
||||||
UserID string
|
UserID string
|
||||||
VerificationCode string
|
Verification *SchemaUserPasswordVerification
|
||||||
CurrentPassword string
|
NewPassword *SchemaUserPassword
|
||||||
Password string
|
|
||||||
EncodedPasswordHash string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Commands) getSchemaUserPasswordWM(ctx context.Context, resourceOwner, id string) (*PasswordV3WriteModel, error) {
|
func (c *Commands) getSchemaUserPasswordWM(ctx context.Context, resourceOwner, id string) (*PasswordV3WriteModel, error) {
|
||||||
@ -165,23 +186,21 @@ func (c *Commands) getSchemaUserPasswordWithVerification(ctx context.Context, us
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := writeModel.Exists(); user.Create && err != nil {
|
if err := writeModel.Exists(); !user.Set && err != nil {
|
||||||
schemauser, err := existingSchemaUser(ctx, c, user.ResourceOwner, user.UserID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
writeModel.ResourceOwner = schemauser.ResourceOwner
|
|
||||||
}
|
|
||||||
|
|
||||||
// if no verification is set, the user must have the permission to change the password
|
// if no verification is set, the user must have the permission to change the password
|
||||||
verification := c.setSchemaUserPasswordWithPermission(writeModel.UserID, writeModel.ResourceOwner)
|
verification := c.setSchemaUserPasswordWithPermission(writeModel.UserID, writeModel.ResourceOwner)
|
||||||
|
if user.Verification != nil {
|
||||||
// otherwise check the password code...
|
// otherwise check the password code...
|
||||||
if user.VerificationCode != "" {
|
if user.Verification.Code != "" {
|
||||||
verification = c.setSchemaUserPasswordWithVerifyCode(writeModel.CodeCreationDate, writeModel.CodeExpiry, writeModel.Code, user.VerificationCode)
|
verification = c.setSchemaUserPasswordWithVerifyCode(writeModel.CodeCreationDate, writeModel.CodeExpiry, writeModel.Code, user.Verification.Code)
|
||||||
}
|
}
|
||||||
// ...or old password
|
// ...or old password
|
||||||
if user.CurrentPassword != "" {
|
if user.Verification.CurrentPassword != "" {
|
||||||
verification = c.checkSchemaUserCurrentPassword(user.Password, user.EncodedPasswordHash, user.CurrentPassword, writeModel.EncodedHash)
|
verification = c.checkSchemaUserCurrentPassword(user.NewPassword.Password, user.NewPassword.EncodedPasswordHash, user.Verification.CurrentPassword, writeModel.EncodedHash)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if verification != nil {
|
if verification != nil {
|
||||||
@ -191,7 +210,7 @@ func (c *Commands) getSchemaUserPasswordWithVerification(ctx context.Context, us
|
|||||||
}
|
}
|
||||||
// use the new hash from the verification in case there is one (e.g. existing pw check)
|
// use the new hash from the verification in case there is one (e.g. existing pw check)
|
||||||
if newEncodedPassword != "" {
|
if newEncodedPassword != "" {
|
||||||
user.EncodedPasswordHash = newEncodedPassword
|
user.NewPassword.EncodedPasswordHash = newEncodedPassword
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return writeModel, nil
|
return writeModel, nil
|
||||||
|
@ -95,6 +95,7 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
|||||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||||
user: &SetSchemaUserPassword{
|
user: &SetSchemaUserPassword{
|
||||||
UserID: "user1",
|
UserID: "user1",
|
||||||
|
Password: &SchemaUserPassword{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
res{
|
res{
|
||||||
@ -108,7 +109,6 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
|||||||
fields{
|
fields{
|
||||||
eventstore: expectEventstore(
|
eventstore: expectEventstore(
|
||||||
expectFilter(),
|
expectFilter(),
|
||||||
expectFilter(),
|
|
||||||
),
|
),
|
||||||
checkPermission: newMockPermissionCheckAllowed(),
|
checkPermission: newMockPermissionCheckAllowed(),
|
||||||
},
|
},
|
||||||
@ -116,7 +116,7 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
|||||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||||
user: &SetSchemaUserPassword{
|
user: &SetSchemaUserPassword{
|
||||||
UserID: "notexisting",
|
UserID: "notexisting",
|
||||||
Password: "password",
|
Password: &SchemaUserPassword{Password: "password"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
res{
|
res{
|
||||||
@ -129,8 +129,9 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
|||||||
"no permission, error",
|
"no permission, error",
|
||||||
fields{
|
fields{
|
||||||
eventstore: expectEventstore(
|
eventstore: expectEventstore(
|
||||||
expectFilter(),
|
|
||||||
filterSchemaUserExisting(),
|
filterSchemaUserExisting(),
|
||||||
|
filterSchemaExisting(),
|
||||||
|
expectFilter(),
|
||||||
),
|
),
|
||||||
checkPermission: newMockPermissionCheckNotAllowed(),
|
checkPermission: newMockPermissionCheckNotAllowed(),
|
||||||
},
|
},
|
||||||
@ -138,7 +139,7 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
|||||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||||
user: &SetSchemaUserPassword{
|
user: &SetSchemaUserPassword{
|
||||||
UserID: "user1",
|
UserID: "user1",
|
||||||
Password: "password",
|
Password: &SchemaUserPassword{Password: "password"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
res{
|
res{
|
||||||
@ -151,8 +152,9 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
|||||||
"password added, ok",
|
"password added, ok",
|
||||||
fields{
|
fields{
|
||||||
eventstore: expectEventstore(
|
eventstore: expectEventstore(
|
||||||
expectFilter(),
|
|
||||||
filterSchemaUserExisting(),
|
filterSchemaUserExisting(),
|
||||||
|
filterSchemaExisting(),
|
||||||
|
expectFilter(),
|
||||||
filterPasswordComplexityPolicyExisting(),
|
filterPasswordComplexityPolicyExisting(),
|
||||||
expectPush(
|
expectPush(
|
||||||
authenticator.NewPasswordCreatedEvent(
|
authenticator.NewPasswordCreatedEvent(
|
||||||
@ -171,10 +173,12 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
|||||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||||
user: &SetSchemaUserPassword{
|
user: &SetSchemaUserPassword{
|
||||||
UserID: "user1",
|
UserID: "user1",
|
||||||
|
Password: &SchemaUserPassword{
|
||||||
Password: "password",
|
Password: "password",
|
||||||
ChangeRequired: false,
|
ChangeRequired: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
res{
|
res{
|
||||||
details: &domain.ObjectDetails{
|
details: &domain.ObjectDetails{
|
||||||
ResourceOwner: "org1",
|
ResourceOwner: "org1",
|
||||||
@ -185,7 +189,9 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
|||||||
"password set, complexity failed",
|
"password set, complexity failed",
|
||||||
fields{
|
fields{
|
||||||
eventstore: expectEventstore(
|
eventstore: expectEventstore(
|
||||||
filterSchemaUserPasswordExisting(),
|
filterSchemaUserExisting(),
|
||||||
|
filterSchemaExisting(),
|
||||||
|
expectFilter(),
|
||||||
filterPasswordComplexityPolicyExisting(),
|
filterPasswordComplexityPolicyExisting(),
|
||||||
expectPush(
|
expectPush(
|
||||||
authenticator.NewPasswordCreatedEvent(
|
authenticator.NewPasswordCreatedEvent(
|
||||||
@ -204,10 +210,12 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
|||||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||||
user: &SetSchemaUserPassword{
|
user: &SetSchemaUserPassword{
|
||||||
UserID: "user1",
|
UserID: "user1",
|
||||||
|
Password: &SchemaUserPassword{
|
||||||
Password: "password",
|
Password: "password",
|
||||||
ChangeRequired: false,
|
ChangeRequired: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
res{
|
res{
|
||||||
details: &domain.ObjectDetails{
|
details: &domain.ObjectDetails{
|
||||||
ResourceOwner: "org1",
|
ResourceOwner: "org1",
|
||||||
@ -218,7 +226,9 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
|||||||
"password set, ok",
|
"password set, ok",
|
||||||
fields{
|
fields{
|
||||||
eventstore: expectEventstore(
|
eventstore: expectEventstore(
|
||||||
filterSchemaUserPasswordExisting(),
|
filterSchemaUserExisting(),
|
||||||
|
filterSchemaExisting(),
|
||||||
|
expectFilter(),
|
||||||
filterPasswordComplexityPolicyExisting(),
|
filterPasswordComplexityPolicyExisting(),
|
||||||
expectPush(
|
expectPush(
|
||||||
authenticator.NewPasswordCreatedEvent(
|
authenticator.NewPasswordCreatedEvent(
|
||||||
@ -237,10 +247,12 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
|||||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||||
user: &SetSchemaUserPassword{
|
user: &SetSchemaUserPassword{
|
||||||
UserID: "user1",
|
UserID: "user1",
|
||||||
|
Password: &SchemaUserPassword{
|
||||||
Password: "password",
|
Password: "password",
|
||||||
ChangeRequired: false,
|
ChangeRequired: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
res{
|
res{
|
||||||
details: &domain.ObjectDetails{
|
details: &domain.ObjectDetails{
|
||||||
ResourceOwner: "org1",
|
ResourceOwner: "org1",
|
||||||
@ -251,7 +263,9 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
|||||||
"password set, changeRequired, ok",
|
"password set, changeRequired, ok",
|
||||||
fields{
|
fields{
|
||||||
eventstore: expectEventstore(
|
eventstore: expectEventstore(
|
||||||
filterSchemaUserPasswordExisting(),
|
filterSchemaUserExisting(),
|
||||||
|
filterSchemaExisting(),
|
||||||
|
expectFilter(),
|
||||||
filterPasswordComplexityPolicyExisting(),
|
filterPasswordComplexityPolicyExisting(),
|
||||||
expectPush(
|
expectPush(
|
||||||
authenticator.NewPasswordCreatedEvent(
|
authenticator.NewPasswordCreatedEvent(
|
||||||
@ -270,10 +284,12 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
|||||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||||
user: &SetSchemaUserPassword{
|
user: &SetSchemaUserPassword{
|
||||||
UserID: "user1",
|
UserID: "user1",
|
||||||
|
Password: &SchemaUserPassword{
|
||||||
Password: "password",
|
Password: "password",
|
||||||
ChangeRequired: true,
|
ChangeRequired: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
res{
|
res{
|
||||||
details: &domain.ObjectDetails{
|
details: &domain.ObjectDetails{
|
||||||
ResourceOwner: "org1",
|
ResourceOwner: "org1",
|
||||||
@ -284,7 +300,9 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
|||||||
"password set, encoded, ok",
|
"password set, encoded, ok",
|
||||||
fields{
|
fields{
|
||||||
eventstore: expectEventstore(
|
eventstore: expectEventstore(
|
||||||
filterSchemaUserPasswordExisting(),
|
filterSchemaUserExisting(),
|
||||||
|
filterSchemaExisting(),
|
||||||
|
expectFilter(),
|
||||||
filterPasswordComplexityPolicyExisting(),
|
filterPasswordComplexityPolicyExisting(),
|
||||||
expectPush(
|
expectPush(
|
||||||
authenticator.NewPasswordCreatedEvent(
|
authenticator.NewPasswordCreatedEvent(
|
||||||
@ -303,11 +321,13 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
|||||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||||
user: &SetSchemaUserPassword{
|
user: &SetSchemaUserPassword{
|
||||||
UserID: "user1",
|
UserID: "user1",
|
||||||
|
Password: &SchemaUserPassword{
|
||||||
Password: "passwordnotused",
|
Password: "passwordnotused",
|
||||||
EncodedPasswordHash: "$plain$x$password2",
|
EncodedPasswordHash: "$plain$x$password2",
|
||||||
ChangeRequired: false,
|
ChangeRequired: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
res{
|
res{
|
||||||
details: &domain.ObjectDetails{
|
details: &domain.ObjectDetails{
|
||||||
ResourceOwner: "org1",
|
ResourceOwner: "org1",
|
||||||
@ -318,6 +338,8 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
|||||||
"password set, current password, ok",
|
"password set, current password, ok",
|
||||||
fields{
|
fields{
|
||||||
eventstore: expectEventstore(
|
eventstore: expectEventstore(
|
||||||
|
filterSchemaUserExisting(),
|
||||||
|
filterSchemaExisting(),
|
||||||
filterSchemaUserPasswordExisting(),
|
filterSchemaUserPasswordExisting(),
|
||||||
filterPasswordComplexityPolicyExisting(),
|
filterPasswordComplexityPolicyExisting(),
|
||||||
expectPush(
|
expectPush(
|
||||||
@ -336,10 +358,14 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
|||||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||||
user: &SetSchemaUserPassword{
|
user: &SetSchemaUserPassword{
|
||||||
UserID: "user1",
|
UserID: "user1",
|
||||||
|
Password: &SchemaUserPassword{
|
||||||
Password: "password2",
|
Password: "password2",
|
||||||
CurrentPassword: "password",
|
|
||||||
ChangeRequired: false,
|
ChangeRequired: false,
|
||||||
},
|
},
|
||||||
|
Verification: &SchemaUserPasswordVerification{
|
||||||
|
CurrentPassword: "password",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
res{
|
res{
|
||||||
details: &domain.ObjectDetails{
|
details: &domain.ObjectDetails{
|
||||||
@ -351,6 +377,8 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
|||||||
"password set, current password, ok",
|
"password set, current password, ok",
|
||||||
fields{
|
fields{
|
||||||
eventstore: expectEventstore(
|
eventstore: expectEventstore(
|
||||||
|
filterSchemaUserExisting(),
|
||||||
|
filterSchemaExisting(),
|
||||||
filterSchemaUserPasswordExisting(),
|
filterSchemaUserPasswordExisting(),
|
||||||
filterPasswordComplexityPolicyExisting(),
|
filterPasswordComplexityPolicyExisting(),
|
||||||
expectPush(
|
expectPush(
|
||||||
@ -369,10 +397,14 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
|||||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||||
user: &SetSchemaUserPassword{
|
user: &SetSchemaUserPassword{
|
||||||
UserID: "user1",
|
UserID: "user1",
|
||||||
|
Password: &SchemaUserPassword{
|
||||||
Password: "password2",
|
Password: "password2",
|
||||||
CurrentPassword: "password",
|
|
||||||
ChangeRequired: false,
|
ChangeRequired: false,
|
||||||
},
|
},
|
||||||
|
Verification: &SchemaUserPasswordVerification{
|
||||||
|
CurrentPassword: "password",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
res{
|
res{
|
||||||
details: &domain.ObjectDetails{
|
details: &domain.ObjectDetails{
|
||||||
@ -383,6 +415,8 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
|||||||
"password set, current password, failed",
|
"password set, current password, failed",
|
||||||
fields{
|
fields{
|
||||||
eventstore: expectEventstore(
|
eventstore: expectEventstore(
|
||||||
|
filterSchemaUserExisting(),
|
||||||
|
filterSchemaExisting(),
|
||||||
filterSchemaUserPasswordExisting(),
|
filterSchemaUserPasswordExisting(),
|
||||||
),
|
),
|
||||||
userPasswordHasher: mockPasswordHasher("x"),
|
userPasswordHasher: mockPasswordHasher("x"),
|
||||||
@ -391,10 +425,14 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
|||||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||||
user: &SetSchemaUserPassword{
|
user: &SetSchemaUserPassword{
|
||||||
UserID: "user1",
|
UserID: "user1",
|
||||||
|
Password: &SchemaUserPassword{
|
||||||
Password: "password2",
|
Password: "password2",
|
||||||
CurrentPassword: "notreally",
|
|
||||||
ChangeRequired: false,
|
ChangeRequired: false,
|
||||||
},
|
},
|
||||||
|
Verification: &SchemaUserPasswordVerification{
|
||||||
|
CurrentPassword: "notreally",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
res{
|
res{
|
||||||
err: func(err error) bool {
|
err: func(err error) bool {
|
||||||
@ -406,6 +444,8 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
|||||||
"password set, code, ok",
|
"password set, code, ok",
|
||||||
fields{
|
fields{
|
||||||
eventstore: expectEventstore(
|
eventstore: expectEventstore(
|
||||||
|
filterSchemaUserExisting(),
|
||||||
|
filterSchemaExisting(),
|
||||||
expectFilter(
|
expectFilter(
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
authenticator.NewPasswordCreatedEvent(
|
authenticator.NewPasswordCreatedEvent(
|
||||||
@ -450,10 +490,14 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
|||||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||||
user: &SetSchemaUserPassword{
|
user: &SetSchemaUserPassword{
|
||||||
UserID: "user1",
|
UserID: "user1",
|
||||||
|
Password: &SchemaUserPassword{
|
||||||
Password: "password2",
|
Password: "password2",
|
||||||
VerificationCode: "code",
|
|
||||||
ChangeRequired: false,
|
ChangeRequired: false,
|
||||||
},
|
},
|
||||||
|
Verification: &SchemaUserPasswordVerification{
|
||||||
|
Code: "code",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
res{
|
res{
|
||||||
details: &domain.ObjectDetails{
|
details: &domain.ObjectDetails{
|
||||||
@ -465,6 +509,8 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
|||||||
"password set, code, failed",
|
"password set, code, failed",
|
||||||
fields{
|
fields{
|
||||||
eventstore: expectEventstore(
|
eventstore: expectEventstore(
|
||||||
|
filterSchemaUserExisting(),
|
||||||
|
filterSchemaExisting(),
|
||||||
expectFilter(
|
expectFilter(
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
authenticator.NewPasswordCreatedEvent(
|
authenticator.NewPasswordCreatedEvent(
|
||||||
@ -499,10 +545,14 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
|||||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||||
user: &SetSchemaUserPassword{
|
user: &SetSchemaUserPassword{
|
||||||
UserID: "user1",
|
UserID: "user1",
|
||||||
|
Password: &SchemaUserPassword{
|
||||||
Password: "password2",
|
Password: "password2",
|
||||||
VerificationCode: "notreally",
|
|
||||||
ChangeRequired: false,
|
ChangeRequired: false,
|
||||||
},
|
},
|
||||||
|
Verification: &SchemaUserPasswordVerification{
|
||||||
|
Code: "notreally",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
res{
|
res{
|
||||||
err: func(err error) bool {
|
err: func(err error) bool {
|
||||||
@ -514,6 +564,8 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
|||||||
"password set, code, no code",
|
"password set, code, no code",
|
||||||
fields{
|
fields{
|
||||||
eventstore: expectEventstore(
|
eventstore: expectEventstore(
|
||||||
|
filterSchemaUserExisting(),
|
||||||
|
filterSchemaExisting(),
|
||||||
filterSchemaUserPasswordExisting(),
|
filterSchemaUserPasswordExisting(),
|
||||||
),
|
),
|
||||||
userPasswordHasher: mockPasswordHasher("x"),
|
userPasswordHasher: mockPasswordHasher("x"),
|
||||||
@ -523,10 +575,14 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
|||||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||||
user: &SetSchemaUserPassword{
|
user: &SetSchemaUserPassword{
|
||||||
UserID: "user1",
|
UserID: "user1",
|
||||||
|
Password: &SchemaUserPassword{
|
||||||
Password: "password2",
|
Password: "password2",
|
||||||
VerificationCode: "notreally",
|
|
||||||
ChangeRequired: false,
|
ChangeRequired: false,
|
||||||
},
|
},
|
||||||
|
Verification: &SchemaUserPasswordVerification{
|
||||||
|
Code: "notreally",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
res{
|
res{
|
||||||
err: func(err error) bool {
|
err: func(err error) bool {
|
||||||
@ -618,7 +674,7 @@ func TestCommands_RequestSchemaUserPasswordReset(t *testing.T) {
|
|||||||
"no permission, error",
|
"no permission, error",
|
||||||
fields{
|
fields{
|
||||||
eventstore: expectEventstore(
|
eventstore: expectEventstore(
|
||||||
expectFilter(),
|
filterSchemaUserPasswordExisting(),
|
||||||
),
|
),
|
||||||
checkPermission: newMockPermissionCheckNotAllowed(),
|
checkPermission: newMockPermissionCheckNotAllowed(),
|
||||||
},
|
},
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/zitadel/zitadel/internal/crypto"
|
"github.com/zitadel/zitadel/internal/crypto"
|
||||||
"github.com/zitadel/zitadel/internal/domain"
|
"github.com/zitadel/zitadel/internal/domain"
|
||||||
|
"github.com/zitadel/zitadel/internal/eventstore"
|
||||||
"github.com/zitadel/zitadel/internal/zerrors"
|
"github.com/zitadel/zitadel/internal/zerrors"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -18,27 +19,24 @@ type AddPAT struct {
|
|||||||
ResourceOwner string
|
ResourceOwner string
|
||||||
UserID string
|
UserID string
|
||||||
|
|
||||||
|
PAT *PAT
|
||||||
|
}
|
||||||
|
|
||||||
|
type PAT struct {
|
||||||
ExpirationDate time.Time
|
ExpirationDate time.Time
|
||||||
Scope []string
|
Scopes []string
|
||||||
Token string
|
Token string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wm *AddPAT) GetExpirationDate() time.Time {
|
func (c *Commands) AddPAT(ctx context.Context, add *AddPAT) (*domain.ObjectDetails, error) {
|
||||||
return wm.ExpirationDate
|
if add.UserID == "" {
|
||||||
}
|
|
||||||
|
|
||||||
func (wm *AddPAT) SetExpirationDate(date time.Time) {
|
|
||||||
wm.ExpirationDate = date
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Commands) AddPAT(ctx context.Context, pat *AddPAT) (*domain.ObjectDetails, error) {
|
|
||||||
if pat.UserID == "" {
|
|
||||||
return nil, zerrors.ThrowInvalidArgument(nil, "COMMAND-14sGR7lTaj", "Errors.IDMissing")
|
return nil, zerrors.ThrowInvalidArgument(nil, "COMMAND-14sGR7lTaj", "Errors.IDMissing")
|
||||||
}
|
}
|
||||||
schemauser, err := existingSchemaUser(ctx, c, pat.ResourceOwner, pat.UserID)
|
schemauser, err := existingSchemaUser(ctx, c, add.ResourceOwner, add.UserID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
add.ResourceOwner = schemauser.ResourceOwner
|
||||||
|
|
||||||
_, err = existingSchema(ctx, c, "", schemauser.SchemaID)
|
_, err = existingSchema(ctx, c, "", schemauser.SchemaID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -46,26 +44,36 @@ func (c *Commands) AddPAT(ctx context.Context, pat *AddPAT) (*domain.ObjectDetai
|
|||||||
}
|
}
|
||||||
// TODO check for possible authenticators
|
// TODO check for possible authenticators
|
||||||
|
|
||||||
id, err := c.idGenerator.Next()
|
writeModel, events, err := c.addPAT(ctx, add.ResourceOwner, add.UserID, add.PAT)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
writeModel, err := c.getSchemaPATWM(ctx, schemauser.ResourceOwner, schemauser.AggregateID, id)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
events, err := writeModel.NewCreate(ctx, pat.ExpirationDate, pat.Scope)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
pat.Token, err = createSchemaUserPAT(c.keyAlgorithm, writeModel.AggregateID, pat.UserID)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return c.pushAppendAndReduceDetails(ctx, writeModel, events...)
|
return c.pushAppendAndReduceDetails(ctx, writeModel, events...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Commands) addPAT(ctx context.Context, resourceOwner, userID string, add *PAT) (*PATV3WriteModel, []eventstore.Command, error) {
|
||||||
|
if add == nil {
|
||||||
|
return nil, nil, nil
|
||||||
|
}
|
||||||
|
id, err := c.idGenerator.Next()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
writeModel, err := c.getSchemaPATWM(ctx, resourceOwner, userID, id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
events, err := writeModel.NewCreate(ctx, add.ExpirationDate, add.Scopes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
add.Token, err = createSchemaUserPAT(c.keyAlgorithm, writeModel.AggregateID, writeModel.UserID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return writeModel, events, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Commands) DeletePAT(ctx context.Context, resourceOwner, userID, id string) (*domain.ObjectDetails, error) {
|
func (c *Commands) DeletePAT(ctx context.Context, resourceOwner, userID, id string) (*domain.ObjectDetails, error) {
|
||||||
if userID == "" {
|
if userID == "" {
|
||||||
return nil, zerrors.ThrowInvalidArgument(nil, "COMMAND-hzqeAXW1qP", "Errors.IDMissing")
|
return nil, zerrors.ThrowInvalidArgument(nil, "COMMAND-hzqeAXW1qP", "Errors.IDMissing")
|
||||||
|
@ -63,7 +63,9 @@ func TestCommands_AddPAT(t *testing.T) {
|
|||||||
},
|
},
|
||||||
args{
|
args{
|
||||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||||
user: &AddPAT{},
|
user: &AddPAT{
|
||||||
|
PAT: &PAT{},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
res{
|
res{
|
||||||
err: func(err error) bool {
|
err: func(err error) bool {
|
||||||
@ -83,6 +85,7 @@ func TestCommands_AddPAT(t *testing.T) {
|
|||||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||||
user: &AddPAT{
|
user: &AddPAT{
|
||||||
UserID: "notexisting",
|
UserID: "notexisting",
|
||||||
|
PAT: &PAT{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
res{
|
res{
|
||||||
@ -106,6 +109,7 @@ func TestCommands_AddPAT(t *testing.T) {
|
|||||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||||
user: &AddPAT{
|
user: &AddPAT{
|
||||||
UserID: "user1",
|
UserID: "user1",
|
||||||
|
PAT: &PAT{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
res{
|
res{
|
||||||
@ -127,6 +131,7 @@ func TestCommands_AddPAT(t *testing.T) {
|
|||||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||||
user: &AddPAT{
|
user: &AddPAT{
|
||||||
UserID: "user1",
|
UserID: "user1",
|
||||||
|
PAT: &PAT{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
res{
|
res{
|
||||||
@ -160,7 +165,9 @@ func TestCommands_AddPAT(t *testing.T) {
|
|||||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||||
user: &AddPAT{
|
user: &AddPAT{
|
||||||
UserID: "user1",
|
UserID: "user1",
|
||||||
Scope: []string{"first", "second", "third"},
|
PAT: &PAT{
|
||||||
|
Scopes: []string{"first", "second", "third"},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
res{
|
res{
|
||||||
@ -195,8 +202,10 @@ func TestCommands_AddPAT(t *testing.T) {
|
|||||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||||
user: &AddPAT{
|
user: &AddPAT{
|
||||||
UserID: "user1",
|
UserID: "user1",
|
||||||
|
PAT: &PAT{
|
||||||
ExpirationDate: time.Date(2024, time.January, 1, 1, 1, 1, 1, time.UTC),
|
ExpirationDate: time.Date(2024, time.January, 1, 1, 1, 1, 1, time.UTC),
|
||||||
Scope: []string{"first", "second", "third"},
|
Scopes: []string{"first", "second", "third"},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
res{
|
res{
|
||||||
@ -224,7 +233,7 @@ func TestCommands_AddPAT(t *testing.T) {
|
|||||||
}
|
}
|
||||||
if tt.res.err == nil {
|
if tt.res.err == nil {
|
||||||
assertObjectDetails(t, tt.res.details, details)
|
assertObjectDetails(t, tt.res.details, details)
|
||||||
assert.Equal(t, tt.res.token, tt.args.user.Token)
|
assert.Equal(t, tt.res.token, tt.args.user.PAT.Token)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/zitadel/zitadel/internal/domain"
|
"github.com/zitadel/zitadel/internal/domain"
|
||||||
|
"github.com/zitadel/zitadel/internal/eventstore"
|
||||||
"github.com/zitadel/zitadel/internal/zerrors"
|
"github.com/zitadel/zitadel/internal/zerrors"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -12,35 +13,47 @@ type AddPublicKey struct {
|
|||||||
ResourceOwner string
|
ResourceOwner string
|
||||||
UserID string
|
UserID string
|
||||||
|
|
||||||
|
PublicKey *PublicKey
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *AddPublicKey) GetPrivateKey() []byte {
|
||||||
|
if wm.PublicKey == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return wm.PublicKey.PrivateKey
|
||||||
|
}
|
||||||
|
|
||||||
|
type PublicKey struct {
|
||||||
ExpirationDate time.Time
|
ExpirationDate time.Time
|
||||||
PublicKey []byte
|
PublicKey []byte
|
||||||
PrivateKey []byte
|
PrivateKey []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wm *AddPublicKey) GetExpirationDate() time.Time {
|
func (wm *PublicKey) GetExpirationDate() time.Time {
|
||||||
return wm.ExpirationDate
|
return wm.ExpirationDate
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wm *AddPublicKey) SetExpirationDate(date time.Time) {
|
func (wm *PublicKey) SetExpirationDate(date time.Time) {
|
||||||
wm.ExpirationDate = date
|
wm.ExpirationDate = date
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wm *AddPublicKey) SetPublicKey(data []byte) {
|
func (wm *PublicKey) SetPublicKey(data []byte) {
|
||||||
wm.PublicKey = data
|
wm.PublicKey = data
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wm *AddPublicKey) SetPrivateKey(data []byte) {
|
func (wm *PublicKey) SetPrivateKey(data []byte) {
|
||||||
wm.PrivateKey = data
|
wm.PrivateKey = data
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Commands) AddPublicKey(ctx context.Context, pk *AddPublicKey) (*domain.ObjectDetails, error) {
|
func (c *Commands) AddPublicKey(ctx context.Context, add *AddPublicKey) (*domain.ObjectDetails, error) {
|
||||||
if pk.UserID == "" {
|
if add.UserID == "" {
|
||||||
return nil, zerrors.ThrowInvalidArgument(nil, "COMMAND-14sGR7lTaj", "Errors.IDMissing")
|
return nil, zerrors.ThrowInvalidArgument(nil, "COMMAND-14sGR7lTaj", "Errors.IDMissing")
|
||||||
}
|
}
|
||||||
schemauser, err := existingSchemaUser(ctx, c, pk.ResourceOwner, pk.UserID)
|
schemauser, err := existingSchemaUser(ctx, c, add.ResourceOwner, add.UserID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
add.ResourceOwner = schemauser.ResourceOwner
|
||||||
|
|
||||||
_, err = existingSchema(ctx, c, "", schemauser.SchemaID)
|
_, err = existingSchema(ctx, c, "", schemauser.SchemaID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -48,28 +61,37 @@ func (c *Commands) AddPublicKey(ctx context.Context, pk *AddPublicKey) (*domain.
|
|||||||
}
|
}
|
||||||
// TODO check for possible authenticators
|
// TODO check for possible authenticators
|
||||||
|
|
||||||
id, err := c.idGenerator.Next()
|
writeModel, events, err := c.addPublicKey(ctx, add.ResourceOwner, add.UserID, add.PublicKey)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
writeModel, err := c.getSchemaPublicKeyWM(ctx, schemauser.ResourceOwner, schemauser.AggregateID, id)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(pk.PublicKey) == 0 {
|
|
||||||
if err := domain.SetNewAuthNKeyPair(pk, c.machineKeySize); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
events, err := writeModel.NewCreate(ctx, pk.ExpirationDate, pk.PublicKey)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return c.pushAppendAndReduceDetails(ctx, writeModel, events...)
|
return c.pushAppendAndReduceDetails(ctx, writeModel, events...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Commands) addPublicKey(ctx context.Context, resourceOwner, userID string, add *PublicKey) (*PublicKeyV3WriteModel, []eventstore.Command, error) {
|
||||||
|
if add == nil {
|
||||||
|
return nil, nil, nil
|
||||||
|
}
|
||||||
|
id, err := c.idGenerator.Next()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
writeModel, err := c.getSchemaPublicKeyWM(ctx, resourceOwner, userID, id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if len(add.PublicKey) == 0 {
|
||||||
|
if err := domain.SetNewAuthNKeyPair(add, c.machineKeySize); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
events, err := writeModel.NewCreate(ctx, add.ExpirationDate, add.PublicKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return writeModel, events, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Commands) DeletePublicKey(ctx context.Context, resourceOwner, userID, id string) (*domain.ObjectDetails, error) {
|
func (c *Commands) DeletePublicKey(ctx context.Context, resourceOwner, userID, id string) (*domain.ObjectDetails, error) {
|
||||||
if userID == "" {
|
if userID == "" {
|
||||||
return nil, zerrors.ThrowInvalidArgument(nil, "COMMAND-hzqeAXW1qP", "Errors.IDMissing")
|
return nil, zerrors.ThrowInvalidArgument(nil, "COMMAND-hzqeAXW1qP", "Errors.IDMissing")
|
||||||
|
@ -102,9 +102,11 @@ func TestCommands_AddPublicKey(t *testing.T) {
|
|||||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||||
user: &AddPublicKey{
|
user: &AddPublicKey{
|
||||||
UserID: "user1",
|
UserID: "user1",
|
||||||
|
PublicKey: &PublicKey{
|
||||||
PublicKey: []byte("something"),
|
PublicKey: []byte("something"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
res{
|
res{
|
||||||
err: func(err error) bool {
|
err: func(err error) bool {
|
||||||
return errors.Is(err, zerrors.ThrowPermissionDenied(nil, "AUTHZ-HKJD33", "Errors.PermissionDenied"))
|
return errors.Is(err, zerrors.ThrowPermissionDenied(nil, "AUTHZ-HKJD33", "Errors.PermissionDenied"))
|
||||||
@ -156,9 +158,11 @@ func TestCommands_AddPublicKey(t *testing.T) {
|
|||||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||||
user: &AddPublicKey{
|
user: &AddPublicKey{
|
||||||
UserID: "user1",
|
UserID: "user1",
|
||||||
|
PublicKey: &PublicKey{
|
||||||
PublicKey: []byte("something"),
|
PublicKey: []byte("something"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
res{
|
res{
|
||||||
details: &domain.ObjectDetails{
|
details: &domain.ObjectDetails{
|
||||||
ResourceOwner: "org1",
|
ResourceOwner: "org1",
|
||||||
@ -189,10 +193,12 @@ func TestCommands_AddPublicKey(t *testing.T) {
|
|||||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||||
user: &AddPublicKey{
|
user: &AddPublicKey{
|
||||||
UserID: "user1",
|
UserID: "user1",
|
||||||
|
PublicKey: &PublicKey{
|
||||||
PublicKey: []byte("something"),
|
PublicKey: []byte("something"),
|
||||||
ExpirationDate: time.Date(2024, time.January, 1, 1, 1, 1, 1, time.UTC),
|
ExpirationDate: time.Date(2024, time.January, 1, 1, 1, 1, 1, time.UTC),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
res{
|
res{
|
||||||
details: &domain.ObjectDetails{
|
details: &domain.ObjectDetails{
|
||||||
ResourceOwner: "org1",
|
ResourceOwner: "org1",
|
||||||
|
@ -16,6 +16,7 @@ import (
|
|||||||
"github.com/zitadel/zitadel/internal/eventstore"
|
"github.com/zitadel/zitadel/internal/eventstore"
|
||||||
"github.com/zitadel/zitadel/internal/id"
|
"github.com/zitadel/zitadel/internal/id"
|
||||||
"github.com/zitadel/zitadel/internal/id/mock"
|
"github.com/zitadel/zitadel/internal/id/mock"
|
||||||
|
"github.com/zitadel/zitadel/internal/repository/user/authenticator"
|
||||||
"github.com/zitadel/zitadel/internal/repository/user/schema"
|
"github.com/zitadel/zitadel/internal/repository/user/schema"
|
||||||
"github.com/zitadel/zitadel/internal/repository/user/schemauser"
|
"github.com/zitadel/zitadel/internal/repository/user/schemauser"
|
||||||
"github.com/zitadel/zitadel/internal/zerrors"
|
"github.com/zitadel/zitadel/internal/zerrors"
|
||||||
@ -27,6 +28,8 @@ func TestCommands_CreateSchemaUser(t *testing.T) {
|
|||||||
idGenerator id.Generator
|
idGenerator id.Generator
|
||||||
checkPermission domain.PermissionCheck
|
checkPermission domain.PermissionCheck
|
||||||
newCode encrypedCodeFunc
|
newCode encrypedCodeFunc
|
||||||
|
userPasswordHasher *crypto.Hasher
|
||||||
|
tokenAlg crypto.EncryptionAlgorithm
|
||||||
}
|
}
|
||||||
type args struct {
|
type args struct {
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
@ -698,6 +701,89 @@ func TestCommands_CreateSchemaUser(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"user created, full authenticators",
|
||||||
|
fields{
|
||||||
|
eventstore: expectEventstore(
|
||||||
|
expectFilter(),
|
||||||
|
filterSchemaExisting(),
|
||||||
|
expectFilter(),
|
||||||
|
expectFilter(),
|
||||||
|
filterPasswordComplexityPolicyExisting(),
|
||||||
|
expectFilter(),
|
||||||
|
expectFilter(),
|
||||||
|
expectPush(
|
||||||
|
schemauser.NewCreatedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&schemauser.NewAggregate("id1", "org1").Aggregate,
|
||||||
|
"type",
|
||||||
|
1,
|
||||||
|
json.RawMessage(`{
|
||||||
|
"name": "user"
|
||||||
|
}`),
|
||||||
|
),
|
||||||
|
authenticator.NewUsernameCreatedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&authenticator.NewAggregate("username1", "org1").Aggregate,
|
||||||
|
"id1",
|
||||||
|
true,
|
||||||
|
"username1",
|
||||||
|
),
|
||||||
|
authenticator.NewPasswordCreatedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&authenticator.NewAggregate("id1", "org1").Aggregate,
|
||||||
|
"id1",
|
||||||
|
"$plain$x$password",
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
authenticator.NewPublicKeyCreatedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&authenticator.NewAggregate("pk1", "org1").Aggregate,
|
||||||
|
"id1",
|
||||||
|
time.Date(2024, time.January, 1, 1, 1, 1, 1, time.UTC),
|
||||||
|
[]byte("something"),
|
||||||
|
),
|
||||||
|
authenticator.NewPATCreatedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&authenticator.NewAggregate("pat1", "org1").Aggregate,
|
||||||
|
"id1",
|
||||||
|
time.Date(2024, time.January, 1, 1, 1, 1, 1, time.UTC),
|
||||||
|
[]string{"first", "second", "third"},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
idGenerator: mock.NewIDGeneratorExpectIDs(t, "id1", "username1", "pk1", "pat1"),
|
||||||
|
checkPermission: newMockPermissionCheckAllowed(),
|
||||||
|
userPasswordHasher: mockPasswordHasher("x"),
|
||||||
|
tokenAlg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||||
|
},
|
||||||
|
args{
|
||||||
|
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||||
|
user: &CreateSchemaUser{
|
||||||
|
ResourceOwner: "org1",
|
||||||
|
SchemaID: "type",
|
||||||
|
Data: json.RawMessage(`{
|
||||||
|
"name": "user"
|
||||||
|
}`),
|
||||||
|
Usernames: []*Username{
|
||||||
|
{Username: "username1", IsOrgSpecific: true},
|
||||||
|
},
|
||||||
|
Password: &SchemaUserPassword{Password: "password"},
|
||||||
|
PublicKeys: []*PublicKey{
|
||||||
|
{PublicKey: []byte("something"), ExpirationDate: time.Date(2024, time.January, 1, 1, 1, 1, 1, time.UTC)},
|
||||||
|
},
|
||||||
|
PATs: []*PAT{
|
||||||
|
{Scopes: []string{"first", "second", "third"}, ExpirationDate: time.Date(2024, time.January, 1, 1, 1, 1, 1, time.UTC)},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res{
|
||||||
|
details: &domain.ObjectDetails{
|
||||||
|
ResourceOwner: "org1",
|
||||||
|
ID: "id1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
@ -707,6 +793,8 @@ func TestCommands_CreateSchemaUser(t *testing.T) {
|
|||||||
checkPermission: tt.fields.checkPermission,
|
checkPermission: tt.fields.checkPermission,
|
||||||
newEncryptedCode: tt.fields.newCode,
|
newEncryptedCode: tt.fields.newCode,
|
||||||
userEncryption: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
userEncryption: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||||
|
userPasswordHasher: tt.fields.userPasswordHasher,
|
||||||
|
keyAlgorithm: tt.fields.tokenAlg,
|
||||||
}
|
}
|
||||||
details, err := c.CreateSchemaUser(tt.args.ctx, tt.args.user)
|
details, err := c.CreateSchemaUser(tt.args.ctx, tt.args.user)
|
||||||
if tt.res.err == nil {
|
if tt.res.err == nil {
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/zitadel/zitadel/internal/domain"
|
"github.com/zitadel/zitadel/internal/domain"
|
||||||
|
"github.com/zitadel/zitadel/internal/eventstore"
|
||||||
"github.com/zitadel/zitadel/internal/zerrors"
|
"github.com/zitadel/zitadel/internal/zerrors"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -11,18 +12,23 @@ type AddUsername struct {
|
|||||||
ResourceOwner string
|
ResourceOwner string
|
||||||
UserID string
|
UserID string
|
||||||
|
|
||||||
|
Username *Username
|
||||||
|
}
|
||||||
|
|
||||||
|
type Username struct {
|
||||||
Username string
|
Username string
|
||||||
IsOrgSpecific bool
|
IsOrgSpecific bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Commands) AddUsername(ctx context.Context, username *AddUsername) (*domain.ObjectDetails, error) {
|
func (c *Commands) AddUsername(ctx context.Context, add *AddUsername) (*domain.ObjectDetails, error) {
|
||||||
if username.UserID == "" {
|
if add.UserID == "" {
|
||||||
return nil, zerrors.ThrowInvalidArgument(nil, "COMMAND-aS3Vz5t6BS", "Errors.IDMissing")
|
return nil, zerrors.ThrowInvalidArgument(nil, "COMMAND-aS3Vz5t6BS", "Errors.IDMissing")
|
||||||
}
|
}
|
||||||
schemauser, err := existingSchemaUser(ctx, c, username.ResourceOwner, username.UserID)
|
schemauser, err := existingSchemaUser(ctx, c, add.ResourceOwner, add.UserID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
add.ResourceOwner = schemauser.ResourceOwner
|
||||||
|
|
||||||
_, err = existingSchema(ctx, c, "", schemauser.SchemaID)
|
_, err = existingSchema(ctx, c, "", schemauser.SchemaID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -30,21 +36,32 @@ func (c *Commands) AddUsername(ctx context.Context, username *AddUsername) (*dom
|
|||||||
}
|
}
|
||||||
// TODO check for possible authenticators
|
// TODO check for possible authenticators
|
||||||
|
|
||||||
id, err := c.idGenerator.Next()
|
writeModel, events, err := c.addUsername(ctx, add.ResourceOwner, add.UserID, add.Username)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
writeModel, err := c.getSchemaUsernameWM(ctx, schemauser.ResourceOwner, schemauser.AggregateID, id)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
events, err := writeModel.NewCreate(ctx, username.IsOrgSpecific, username.Username)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return c.pushAppendAndReduceDetails(ctx, writeModel, events...)
|
return c.pushAppendAndReduceDetails(ctx, writeModel, events...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Commands) addUsername(ctx context.Context, resourceOwner, userID string, add *Username) (*UsernameV3WriteModel, []eventstore.Command, error) {
|
||||||
|
if resourceOwner == "" || userID == "" || add == nil {
|
||||||
|
return nil, nil, nil
|
||||||
|
}
|
||||||
|
id, err := c.idGenerator.Next()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
writeModel, err := c.getSchemaUsernameWM(ctx, resourceOwner, userID, id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
events, err := writeModel.NewCreate(ctx, add.IsOrgSpecific, add.Username)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return writeModel, events, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Commands) DeleteUsername(ctx context.Context, resourceOwner, userID, id string) (*domain.ObjectDetails, error) {
|
func (c *Commands) DeleteUsername(ctx context.Context, resourceOwner, userID, id string) (*domain.ObjectDetails, error) {
|
||||||
if userID == "" {
|
if userID == "" {
|
||||||
return nil, zerrors.ThrowInvalidArgument(nil, "COMMAND-J6ybG5WZiy", "Errors.IDMissing")
|
return nil, zerrors.ThrowInvalidArgument(nil, "COMMAND-J6ybG5WZiy", "Errors.IDMissing")
|
||||||
|
@ -142,6 +142,9 @@ func TestCommands_AddUsername(t *testing.T) {
|
|||||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||||
user: &AddUsername{
|
user: &AddUsername{
|
||||||
UserID: "user1",
|
UserID: "user1",
|
||||||
|
Username: &Username{
|
||||||
|
Username: "user1",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
res{
|
res{
|
||||||
@ -163,6 +166,9 @@ func TestCommands_AddUsername(t *testing.T) {
|
|||||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||||
user: &AddUsername{
|
user: &AddUsername{
|
||||||
UserID: "user1",
|
UserID: "user1",
|
||||||
|
Username: &Username{
|
||||||
|
Username: "user1",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
res{
|
res{
|
||||||
@ -195,10 +201,12 @@ func TestCommands_AddUsername(t *testing.T) {
|
|||||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||||
user: &AddUsername{
|
user: &AddUsername{
|
||||||
UserID: "user1",
|
UserID: "user1",
|
||||||
|
Username: &Username{
|
||||||
Username: "username",
|
Username: "username",
|
||||||
IsOrgSpecific: false,
|
IsOrgSpecific: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
res{
|
res{
|
||||||
details: &domain.ObjectDetails{
|
details: &domain.ObjectDetails{
|
||||||
ResourceOwner: "org1",
|
ResourceOwner: "org1",
|
||||||
@ -229,10 +237,12 @@ func TestCommands_AddUsername(t *testing.T) {
|
|||||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||||
user: &AddUsername{
|
user: &AddUsername{
|
||||||
UserID: "user1",
|
UserID: "user1",
|
||||||
|
Username: &Username{
|
||||||
Username: "username",
|
Username: "username",
|
||||||
IsOrgSpecific: true,
|
IsOrgSpecific: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
res{
|
res{
|
||||||
details: &domain.ObjectDetails{
|
details: &domain.ObjectDetails{
|
||||||
ResourceOwner: "org1",
|
ResourceOwner: "org1",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user