mirror of
https://github.com/zitadel/zitadel.git
synced 2025-04-25 20:20:51 +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 {
|
||||
pw, verification := setPasswordToSetSchemaUserPassword(req.GetNewPassword())
|
||||
return &command.SetSchemaUserPassword{
|
||||
ResourceOwner: organizationToUpdateResourceOwner(req.Organization),
|
||||
UserID: req.GetId(),
|
||||
Password: req.GetNewPassword().GetPassword(),
|
||||
EncodedPasswordHash: req.GetNewPassword().GetHash(),
|
||||
ChangeRequired: req.GetNewPassword().GetChangeRequired(),
|
||||
VerificationCode: req.GetNewPassword().GetVerificationCode(),
|
||||
CurrentPassword: req.GetNewPassword().GetCurrentPassword(),
|
||||
ResourceOwner: organizationToUpdateResourceOwner(req.Organization),
|
||||
UserID: req.GetId(),
|
||||
Password: pw,
|
||||
Verification: verification,
|
||||
}
|
||||
}
|
||||
|
||||
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{
|
||||
Details: resource_object.DomainToDetailsPb(details, object.OwnerType_OWNER_TYPE_ORG, details.ResourceOwner),
|
||||
PersonalAccessTokenId: details.ID,
|
||||
PersonalAccessToken: pat.Token,
|
||||
PersonalAccessToken: pat.PAT.Token,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func addPersonalAccessTokenRequestToAddPAT(req *user.AddPersonalAccessTokenRequest) *command.AddPAT {
|
||||
expDate := time.Time{}
|
||||
if req.GetPersonalAccessToken().GetExpirationDate() != nil {
|
||||
expDate = req.GetPersonalAccessToken().GetExpirationDate().AsTime()
|
||||
if req == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &command.AddPAT{
|
||||
ResourceOwner: organizationToUpdateResourceOwner(req.Organization),
|
||||
UserID: req.GetId(),
|
||||
ResourceOwner: organizationToUpdateResourceOwner(req.Organization),
|
||||
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,
|
||||
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{
|
||||
Details: resource_object.DomainToDetailsPb(details, object.OwnerType_OWNER_TYPE_ORG, details.ResourceOwner),
|
||||
PublicKeyId: details.ID,
|
||||
PrivateKey: pk.PrivateKey,
|
||||
PrivateKey: pk.GetPrivateKey(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func addPublicKeyRequestToAddPublicKey(req *user.AddPublicKeyRequest) *command.AddPublicKey {
|
||||
expDate := time.Time{}
|
||||
if req.GetPublicKey().GetExpirationDate() != nil {
|
||||
expDate = req.GetPublicKey().GetExpirationDate().AsTime()
|
||||
if req == nil {
|
||||
return nil
|
||||
}
|
||||
return &command.AddPublicKey{
|
||||
ResourceOwner: organizationToUpdateResourceOwner(req.Organization),
|
||||
UserID: req.GetId(),
|
||||
PublicKey: req.GetPublicKey().GetPublicKey().GetPublicKey(),
|
||||
ResourceOwner: organizationToUpdateResourceOwner(req.Organization),
|
||||
UserID: req.GetId(),
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
@ -30,20 +30,54 @@ func (s *Server) CreateUser(ctx context.Context, req *user.CreateUserRequest) (_
|
||||
}, 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) {
|
||||
data, err := req.GetUser().GetData().MarshalJSON()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &command.CreateSchemaUser{
|
||||
user := &command.CreateSchemaUser{
|
||||
ResourceOwner: organizationToCreateResourceOwner(ctx, req.Organization),
|
||||
SchemaID: req.GetUser().GetSchemaId(),
|
||||
ID: req.GetUser().GetUserId(),
|
||||
Data: data,
|
||||
Email: setEmailToEmail(req.GetUser().GetContact().GetEmail()),
|
||||
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 {
|
||||
|
@ -24,11 +24,23 @@ func (s *Server) AddUsername(ctx context.Context, req *user.AddUsernameRequest)
|
||||
}
|
||||
|
||||
func addUsernameRequestToAddUsername(req *user.AddUsernameRequest) *command.AddUsername {
|
||||
if req == nil {
|
||||
return nil
|
||||
}
|
||||
return &command.AddUsername{
|
||||
ResourceOwner: organizationToUpdateResourceOwner(req.Organization),
|
||||
UserID: req.GetId(),
|
||||
Username: req.GetUsername().GetUsername(),
|
||||
IsOrgSpecific: req.GetUsername().GetIsOrganizationSpecific(),
|
||||
Username: setUsernameToAddUsername(req.GetUsername()),
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
Phone *Phone
|
||||
ReturnCodePhone *string
|
||||
|
||||
Usernames []*Username
|
||||
Password *SchemaUserPassword
|
||||
PublicKeys []*PublicKey
|
||||
PATs []*PAT
|
||||
}
|
||||
|
||||
func (s *CreateSchemaUser) Valid() (err error) {
|
||||
@ -84,6 +89,34 @@ func (c *Commands) CreateSchemaUser(ctx context.Context, user *CreateSchemaUser)
|
||||
if 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...)
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/telemetry/tracing"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
@ -14,19 +15,22 @@ type SetSchemaUserPassword struct {
|
||||
ResourceOwner string
|
||||
UserID string
|
||||
|
||||
Verification *SchemaUserPasswordVerification
|
||||
Password *SchemaUserPassword
|
||||
}
|
||||
|
||||
type SchemaUserPasswordVerification struct {
|
||||
CurrentPassword string
|
||||
Code string
|
||||
}
|
||||
|
||||
type SchemaUserPassword struct {
|
||||
Password string
|
||||
EncodedPasswordHash string
|
||||
ChangeRequired bool
|
||||
|
||||
CurrentPassword string
|
||||
VerificationCode string
|
||||
}
|
||||
|
||||
func (p *SetSchemaUserPassword) Validate(hasher *crypto.Hasher) (err error) {
|
||||
if p.UserID == "" {
|
||||
return zerrors.ThrowInvalidArgument(nil, "COMMAND-aS3Vz5t6BS", "Errors.IDMissing")
|
||||
}
|
||||
|
||||
func (p *SchemaUserPassword) Validate(hasher *crypto.Hasher) (err error) {
|
||||
if p.EncodedPasswordHash != "" {
|
||||
if !hasher.EncodingSupported(p.EncodedPasswordHash) {
|
||||
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 == "" {
|
||||
return zerrors.ThrowInvalidArgument(nil, "COMMAND-3klek4sbns", "Errors.User.Password.Empty")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Commands) SetSchemaUserPassword(ctx context.Context, user *SetSchemaUserPassword) (*domain.ObjectDetails, error) {
|
||||
if err := user.Validate(c.userPasswordHasher); err != nil {
|
||||
func (c *Commands) SetSchemaUserPassword(ctx context.Context, set *SetSchemaUserPassword) (*domain.ObjectDetails, error) {
|
||||
if set.UserID == "" {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "COMMAND-aS3Vz5t6BS", "Errors.IDMissing")
|
||||
}
|
||||
if err := set.Password.Validate(c.userPasswordHasher); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
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)
|
||||
schemauser, err := existingSchemaUser(ctx, c, set.ResourceOwner, set.UserID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
set.ResourceOwner = schemauser.ResourceOwner
|
||||
|
||||
// If password is provided, let's check if is compliant with the policy.
|
||||
// If only a encodedPassword is passed, we can skip this.
|
||||
if user.Password != "" {
|
||||
if err = c.checkPasswordComplexity(ctx, user.Password, writeModel.ResourceOwner); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = existingSchema(ctx, c, "", schemauser.SchemaID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// TODO check for possible authenticators
|
||||
|
||||
encodedPassword := schemaUser.EncodedPasswordHash
|
||||
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,
|
||||
)
|
||||
writeModel, events, err := c.setSchemaUserPassword(ctx, set.ResourceOwner, set.UserID, set.Verification, set.Password)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
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 {
|
||||
ResourceOwner string
|
||||
UserID string
|
||||
@ -132,13 +155,11 @@ func (c *Commands) DeleteSchemaUserPassword(ctx context.Context, resourceOwner,
|
||||
}
|
||||
|
||||
type schemaUserPassword struct {
|
||||
Create bool
|
||||
ResourceOwner string
|
||||
UserID string
|
||||
VerificationCode string
|
||||
CurrentPassword string
|
||||
Password string
|
||||
EncodedPasswordHash string
|
||||
Set bool
|
||||
ResourceOwner string
|
||||
UserID string
|
||||
Verification *SchemaUserPasswordVerification
|
||||
NewPassword *SchemaUserPassword
|
||||
}
|
||||
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
if err := writeModel.Exists(); user.Create && err != nil {
|
||||
schemauser, err := existingSchemaUser(ctx, c, user.ResourceOwner, user.UserID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
writeModel.ResourceOwner = schemauser.ResourceOwner
|
||||
if err := writeModel.Exists(); !user.Set && err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// if no verification is set, the user must have the permission to change the password
|
||||
verification := c.setSchemaUserPasswordWithPermission(writeModel.UserID, writeModel.ResourceOwner)
|
||||
// otherwise check the password code...
|
||||
if user.VerificationCode != "" {
|
||||
verification = c.setSchemaUserPasswordWithVerifyCode(writeModel.CodeCreationDate, writeModel.CodeExpiry, writeModel.Code, user.VerificationCode)
|
||||
}
|
||||
// ...or old password
|
||||
if user.CurrentPassword != "" {
|
||||
verification = c.checkSchemaUserCurrentPassword(user.Password, user.EncodedPasswordHash, user.CurrentPassword, writeModel.EncodedHash)
|
||||
if user.Verification != nil {
|
||||
// otherwise check the password code...
|
||||
if user.Verification.Code != "" {
|
||||
verification = c.setSchemaUserPasswordWithVerifyCode(writeModel.CodeCreationDate, writeModel.CodeExpiry, writeModel.Code, user.Verification.Code)
|
||||
}
|
||||
// ...or old password
|
||||
if user.Verification.CurrentPassword != "" {
|
||||
verification = c.checkSchemaUserCurrentPassword(user.NewPassword.Password, user.NewPassword.EncodedPasswordHash, user.Verification.CurrentPassword, writeModel.EncodedHash)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
if newEncodedPassword != "" {
|
||||
user.EncodedPasswordHash = newEncodedPassword
|
||||
user.NewPassword.EncodedPasswordHash = newEncodedPassword
|
||||
}
|
||||
}
|
||||
return writeModel, nil
|
||||
|
@ -94,7 +94,8 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
||||
args{
|
||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||
user: &SetSchemaUserPassword{
|
||||
UserID: "user1",
|
||||
UserID: "user1",
|
||||
Password: &SchemaUserPassword{},
|
||||
},
|
||||
},
|
||||
res{
|
||||
@ -108,7 +109,6 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
||||
fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(),
|
||||
expectFilter(),
|
||||
),
|
||||
checkPermission: newMockPermissionCheckAllowed(),
|
||||
},
|
||||
@ -116,7 +116,7 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||
user: &SetSchemaUserPassword{
|
||||
UserID: "notexisting",
|
||||
Password: "password",
|
||||
Password: &SchemaUserPassword{Password: "password"},
|
||||
},
|
||||
},
|
||||
res{
|
||||
@ -129,8 +129,9 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
||||
"no permission, error",
|
||||
fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(),
|
||||
filterSchemaUserExisting(),
|
||||
filterSchemaExisting(),
|
||||
expectFilter(),
|
||||
),
|
||||
checkPermission: newMockPermissionCheckNotAllowed(),
|
||||
},
|
||||
@ -138,7 +139,7 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||
user: &SetSchemaUserPassword{
|
||||
UserID: "user1",
|
||||
Password: "password",
|
||||
Password: &SchemaUserPassword{Password: "password"},
|
||||
},
|
||||
},
|
||||
res{
|
||||
@ -151,8 +152,9 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
||||
"password added, ok",
|
||||
fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(),
|
||||
filterSchemaUserExisting(),
|
||||
filterSchemaExisting(),
|
||||
expectFilter(),
|
||||
filterPasswordComplexityPolicyExisting(),
|
||||
expectPush(
|
||||
authenticator.NewPasswordCreatedEvent(
|
||||
@ -170,9 +172,11 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
||||
args{
|
||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||
user: &SetSchemaUserPassword{
|
||||
UserID: "user1",
|
||||
Password: "password",
|
||||
ChangeRequired: false,
|
||||
UserID: "user1",
|
||||
Password: &SchemaUserPassword{
|
||||
Password: "password",
|
||||
ChangeRequired: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
res{
|
||||
@ -185,7 +189,9 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
||||
"password set, complexity failed",
|
||||
fields{
|
||||
eventstore: expectEventstore(
|
||||
filterSchemaUserPasswordExisting(),
|
||||
filterSchemaUserExisting(),
|
||||
filterSchemaExisting(),
|
||||
expectFilter(),
|
||||
filterPasswordComplexityPolicyExisting(),
|
||||
expectPush(
|
||||
authenticator.NewPasswordCreatedEvent(
|
||||
@ -203,9 +209,11 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
||||
args{
|
||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||
user: &SetSchemaUserPassword{
|
||||
UserID: "user1",
|
||||
Password: "password",
|
||||
ChangeRequired: false,
|
||||
UserID: "user1",
|
||||
Password: &SchemaUserPassword{
|
||||
Password: "password",
|
||||
ChangeRequired: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
res{
|
||||
@ -218,7 +226,9 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
||||
"password set, ok",
|
||||
fields{
|
||||
eventstore: expectEventstore(
|
||||
filterSchemaUserPasswordExisting(),
|
||||
filterSchemaUserExisting(),
|
||||
filterSchemaExisting(),
|
||||
expectFilter(),
|
||||
filterPasswordComplexityPolicyExisting(),
|
||||
expectPush(
|
||||
authenticator.NewPasswordCreatedEvent(
|
||||
@ -236,9 +246,11 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
||||
args{
|
||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||
user: &SetSchemaUserPassword{
|
||||
UserID: "user1",
|
||||
Password: "password",
|
||||
ChangeRequired: false,
|
||||
UserID: "user1",
|
||||
Password: &SchemaUserPassword{
|
||||
Password: "password",
|
||||
ChangeRequired: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
res{
|
||||
@ -251,7 +263,9 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
||||
"password set, changeRequired, ok",
|
||||
fields{
|
||||
eventstore: expectEventstore(
|
||||
filterSchemaUserPasswordExisting(),
|
||||
filterSchemaUserExisting(),
|
||||
filterSchemaExisting(),
|
||||
expectFilter(),
|
||||
filterPasswordComplexityPolicyExisting(),
|
||||
expectPush(
|
||||
authenticator.NewPasswordCreatedEvent(
|
||||
@ -269,9 +283,11 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
||||
args{
|
||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||
user: &SetSchemaUserPassword{
|
||||
UserID: "user1",
|
||||
Password: "password",
|
||||
ChangeRequired: true,
|
||||
UserID: "user1",
|
||||
Password: &SchemaUserPassword{
|
||||
Password: "password",
|
||||
ChangeRequired: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
res{
|
||||
@ -284,7 +300,9 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
||||
"password set, encoded, ok",
|
||||
fields{
|
||||
eventstore: expectEventstore(
|
||||
filterSchemaUserPasswordExisting(),
|
||||
filterSchemaUserExisting(),
|
||||
filterSchemaExisting(),
|
||||
expectFilter(),
|
||||
filterPasswordComplexityPolicyExisting(),
|
||||
expectPush(
|
||||
authenticator.NewPasswordCreatedEvent(
|
||||
@ -302,10 +320,12 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
||||
args{
|
||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||
user: &SetSchemaUserPassword{
|
||||
UserID: "user1",
|
||||
Password: "passwordnotused",
|
||||
EncodedPasswordHash: "$plain$x$password2",
|
||||
ChangeRequired: false,
|
||||
UserID: "user1",
|
||||
Password: &SchemaUserPassword{
|
||||
Password: "passwordnotused",
|
||||
EncodedPasswordHash: "$plain$x$password2",
|
||||
ChangeRequired: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
res{
|
||||
@ -318,6 +338,8 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
||||
"password set, current password, ok",
|
||||
fields{
|
||||
eventstore: expectEventstore(
|
||||
filterSchemaUserExisting(),
|
||||
filterSchemaExisting(),
|
||||
filterSchemaUserPasswordExisting(),
|
||||
filterPasswordComplexityPolicyExisting(),
|
||||
expectPush(
|
||||
@ -335,10 +357,14 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
||||
args{
|
||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||
user: &SetSchemaUserPassword{
|
||||
UserID: "user1",
|
||||
Password: "password2",
|
||||
CurrentPassword: "password",
|
||||
ChangeRequired: false,
|
||||
UserID: "user1",
|
||||
Password: &SchemaUserPassword{
|
||||
Password: "password2",
|
||||
ChangeRequired: false,
|
||||
},
|
||||
Verification: &SchemaUserPasswordVerification{
|
||||
CurrentPassword: "password",
|
||||
},
|
||||
},
|
||||
},
|
||||
res{
|
||||
@ -351,6 +377,8 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
||||
"password set, current password, ok",
|
||||
fields{
|
||||
eventstore: expectEventstore(
|
||||
filterSchemaUserExisting(),
|
||||
filterSchemaExisting(),
|
||||
filterSchemaUserPasswordExisting(),
|
||||
filterPasswordComplexityPolicyExisting(),
|
||||
expectPush(
|
||||
@ -368,10 +396,14 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
||||
args{
|
||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||
user: &SetSchemaUserPassword{
|
||||
UserID: "user1",
|
||||
Password: "password2",
|
||||
CurrentPassword: "password",
|
||||
ChangeRequired: false,
|
||||
UserID: "user1",
|
||||
Password: &SchemaUserPassword{
|
||||
Password: "password2",
|
||||
ChangeRequired: false,
|
||||
},
|
||||
Verification: &SchemaUserPasswordVerification{
|
||||
CurrentPassword: "password",
|
||||
},
|
||||
},
|
||||
},
|
||||
res{
|
||||
@ -383,6 +415,8 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
||||
"password set, current password, failed",
|
||||
fields{
|
||||
eventstore: expectEventstore(
|
||||
filterSchemaUserExisting(),
|
||||
filterSchemaExisting(),
|
||||
filterSchemaUserPasswordExisting(),
|
||||
),
|
||||
userPasswordHasher: mockPasswordHasher("x"),
|
||||
@ -390,10 +424,14 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
||||
args{
|
||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||
user: &SetSchemaUserPassword{
|
||||
UserID: "user1",
|
||||
Password: "password2",
|
||||
CurrentPassword: "notreally",
|
||||
ChangeRequired: false,
|
||||
UserID: "user1",
|
||||
Password: &SchemaUserPassword{
|
||||
Password: "password2",
|
||||
ChangeRequired: false,
|
||||
},
|
||||
Verification: &SchemaUserPasswordVerification{
|
||||
CurrentPassword: "notreally",
|
||||
},
|
||||
},
|
||||
},
|
||||
res{
|
||||
@ -406,6 +444,8 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
||||
"password set, code, ok",
|
||||
fields{
|
||||
eventstore: expectEventstore(
|
||||
filterSchemaUserExisting(),
|
||||
filterSchemaExisting(),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
authenticator.NewPasswordCreatedEvent(
|
||||
@ -449,10 +489,14 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
||||
args{
|
||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||
user: &SetSchemaUserPassword{
|
||||
UserID: "user1",
|
||||
Password: "password2",
|
||||
VerificationCode: "code",
|
||||
ChangeRequired: false,
|
||||
UserID: "user1",
|
||||
Password: &SchemaUserPassword{
|
||||
Password: "password2",
|
||||
ChangeRequired: false,
|
||||
},
|
||||
Verification: &SchemaUserPasswordVerification{
|
||||
Code: "code",
|
||||
},
|
||||
},
|
||||
},
|
||||
res{
|
||||
@ -465,6 +509,8 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
||||
"password set, code, failed",
|
||||
fields{
|
||||
eventstore: expectEventstore(
|
||||
filterSchemaUserExisting(),
|
||||
filterSchemaExisting(),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
authenticator.NewPasswordCreatedEvent(
|
||||
@ -498,10 +544,14 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
||||
args{
|
||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||
user: &SetSchemaUserPassword{
|
||||
UserID: "user1",
|
||||
Password: "password2",
|
||||
VerificationCode: "notreally",
|
||||
ChangeRequired: false,
|
||||
UserID: "user1",
|
||||
Password: &SchemaUserPassword{
|
||||
Password: "password2",
|
||||
ChangeRequired: false,
|
||||
},
|
||||
Verification: &SchemaUserPasswordVerification{
|
||||
Code: "notreally",
|
||||
},
|
||||
},
|
||||
},
|
||||
res{
|
||||
@ -514,6 +564,8 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
||||
"password set, code, no code",
|
||||
fields{
|
||||
eventstore: expectEventstore(
|
||||
filterSchemaUserExisting(),
|
||||
filterSchemaExisting(),
|
||||
filterSchemaUserPasswordExisting(),
|
||||
),
|
||||
userPasswordHasher: mockPasswordHasher("x"),
|
||||
@ -522,10 +574,14 @@ func TestCommands_SetSchemaUserPassword(t *testing.T) {
|
||||
args{
|
||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||
user: &SetSchemaUserPassword{
|
||||
UserID: "user1",
|
||||
Password: "password2",
|
||||
VerificationCode: "notreally",
|
||||
ChangeRequired: false,
|
||||
UserID: "user1",
|
||||
Password: &SchemaUserPassword{
|
||||
Password: "password2",
|
||||
ChangeRequired: false,
|
||||
},
|
||||
Verification: &SchemaUserPasswordVerification{
|
||||
Code: "notreally",
|
||||
},
|
||||
},
|
||||
},
|
||||
res{
|
||||
@ -618,7 +674,7 @@ func TestCommands_RequestSchemaUserPasswordReset(t *testing.T) {
|
||||
"no permission, error",
|
||||
fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(),
|
||||
filterSchemaUserPasswordExisting(),
|
||||
),
|
||||
checkPermission: newMockPermissionCheckNotAllowed(),
|
||||
},
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
@ -18,27 +19,24 @@ type AddPAT struct {
|
||||
ResourceOwner string
|
||||
UserID string
|
||||
|
||||
PAT *PAT
|
||||
}
|
||||
|
||||
type PAT struct {
|
||||
ExpirationDate time.Time
|
||||
Scope []string
|
||||
Scopes []string
|
||||
Token string
|
||||
}
|
||||
|
||||
func (wm *AddPAT) GetExpirationDate() time.Time {
|
||||
return wm.ExpirationDate
|
||||
}
|
||||
|
||||
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 == "" {
|
||||
func (c *Commands) AddPAT(ctx context.Context, add *AddPAT) (*domain.ObjectDetails, error) {
|
||||
if add.UserID == "" {
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
add.ResourceOwner = schemauser.ResourceOwner
|
||||
|
||||
_, err = existingSchema(ctx, c, "", schemauser.SchemaID)
|
||||
if err != nil {
|
||||
@ -46,26 +44,36 @@ func (c *Commands) AddPAT(ctx context.Context, pat *AddPAT) (*domain.ObjectDetai
|
||||
}
|
||||
// TODO check for possible authenticators
|
||||
|
||||
id, err := c.idGenerator.Next()
|
||||
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)
|
||||
writeModel, events, err := c.addPAT(ctx, add.ResourceOwner, add.UserID, add.PAT)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
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) {
|
||||
if userID == "" {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "COMMAND-hzqeAXW1qP", "Errors.IDMissing")
|
||||
|
@ -62,8 +62,10 @@ func TestCommands_AddPAT(t *testing.T) {
|
||||
checkPermission: newMockPermissionCheckAllowed(),
|
||||
},
|
||||
args{
|
||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||
user: &AddPAT{},
|
||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||
user: &AddPAT{
|
||||
PAT: &PAT{},
|
||||
},
|
||||
},
|
||||
res{
|
||||
err: func(err error) bool {
|
||||
@ -83,6 +85,7 @@ func TestCommands_AddPAT(t *testing.T) {
|
||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||
user: &AddPAT{
|
||||
UserID: "notexisting",
|
||||
PAT: &PAT{},
|
||||
},
|
||||
},
|
||||
res{
|
||||
@ -106,6 +109,7 @@ func TestCommands_AddPAT(t *testing.T) {
|
||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||
user: &AddPAT{
|
||||
UserID: "user1",
|
||||
PAT: &PAT{},
|
||||
},
|
||||
},
|
||||
res{
|
||||
@ -127,6 +131,7 @@ func TestCommands_AddPAT(t *testing.T) {
|
||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||
user: &AddPAT{
|
||||
UserID: "user1",
|
||||
PAT: &PAT{},
|
||||
},
|
||||
},
|
||||
res{
|
||||
@ -160,7 +165,9 @@ func TestCommands_AddPAT(t *testing.T) {
|
||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||
user: &AddPAT{
|
||||
UserID: "user1",
|
||||
Scope: []string{"first", "second", "third"},
|
||||
PAT: &PAT{
|
||||
Scopes: []string{"first", "second", "third"},
|
||||
},
|
||||
},
|
||||
},
|
||||
res{
|
||||
@ -194,9 +201,11 @@ func TestCommands_AddPAT(t *testing.T) {
|
||||
args{
|
||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||
user: &AddPAT{
|
||||
UserID: "user1",
|
||||
ExpirationDate: time.Date(2024, time.January, 1, 1, 1, 1, 1, time.UTC),
|
||||
Scope: []string{"first", "second", "third"},
|
||||
UserID: "user1",
|
||||
PAT: &PAT{
|
||||
ExpirationDate: time.Date(2024, time.January, 1, 1, 1, 1, 1, time.UTC),
|
||||
Scopes: []string{"first", "second", "third"},
|
||||
},
|
||||
},
|
||||
},
|
||||
res{
|
||||
@ -224,7 +233,7 @@ func TestCommands_AddPAT(t *testing.T) {
|
||||
}
|
||||
if tt.res.err == nil {
|
||||
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"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
@ -12,35 +13,47 @@ type AddPublicKey struct {
|
||||
ResourceOwner 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
|
||||
PublicKey []byte
|
||||
PrivateKey []byte
|
||||
}
|
||||
|
||||
func (wm *AddPublicKey) GetExpirationDate() time.Time {
|
||||
func (wm *PublicKey) GetExpirationDate() time.Time {
|
||||
return wm.ExpirationDate
|
||||
}
|
||||
|
||||
func (wm *AddPublicKey) SetExpirationDate(date time.Time) {
|
||||
func (wm *PublicKey) SetExpirationDate(date time.Time) {
|
||||
wm.ExpirationDate = date
|
||||
}
|
||||
|
||||
func (wm *AddPublicKey) SetPublicKey(data []byte) {
|
||||
func (wm *PublicKey) SetPublicKey(data []byte) {
|
||||
wm.PublicKey = data
|
||||
}
|
||||
|
||||
func (wm *AddPublicKey) SetPrivateKey(data []byte) {
|
||||
func (wm *PublicKey) SetPrivateKey(data []byte) {
|
||||
wm.PrivateKey = data
|
||||
}
|
||||
|
||||
func (c *Commands) AddPublicKey(ctx context.Context, pk *AddPublicKey) (*domain.ObjectDetails, error) {
|
||||
if pk.UserID == "" {
|
||||
func (c *Commands) AddPublicKey(ctx context.Context, add *AddPublicKey) (*domain.ObjectDetails, error) {
|
||||
if add.UserID == "" {
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
add.ResourceOwner = schemauser.ResourceOwner
|
||||
|
||||
_, err = existingSchema(ctx, c, "", schemauser.SchemaID)
|
||||
if err != nil {
|
||||
@ -48,28 +61,37 @@ func (c *Commands) AddPublicKey(ctx context.Context, pk *AddPublicKey) (*domain.
|
||||
}
|
||||
// TODO check for possible authenticators
|
||||
|
||||
id, err := c.idGenerator.Next()
|
||||
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)
|
||||
writeModel, events, err := c.addPublicKey(ctx, add.ResourceOwner, add.UserID, add.PublicKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
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) {
|
||||
if userID == "" {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "COMMAND-hzqeAXW1qP", "Errors.IDMissing")
|
||||
|
@ -101,8 +101,10 @@ func TestCommands_AddPublicKey(t *testing.T) {
|
||||
args{
|
||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||
user: &AddPublicKey{
|
||||
UserID: "user1",
|
||||
PublicKey: []byte("something"),
|
||||
UserID: "user1",
|
||||
PublicKey: &PublicKey{
|
||||
PublicKey: []byte("something"),
|
||||
},
|
||||
},
|
||||
},
|
||||
res{
|
||||
@ -155,8 +157,10 @@ func TestCommands_AddPublicKey(t *testing.T) {
|
||||
args{
|
||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||
user: &AddPublicKey{
|
||||
UserID: "user1",
|
||||
PublicKey: []byte("something"),
|
||||
UserID: "user1",
|
||||
PublicKey: &PublicKey{
|
||||
PublicKey: []byte("something"),
|
||||
},
|
||||
},
|
||||
},
|
||||
res{
|
||||
@ -188,9 +192,11 @@ func TestCommands_AddPublicKey(t *testing.T) {
|
||||
args{
|
||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||
user: &AddPublicKey{
|
||||
UserID: "user1",
|
||||
PublicKey: []byte("something"),
|
||||
ExpirationDate: time.Date(2024, time.January, 1, 1, 1, 1, 1, time.UTC),
|
||||
UserID: "user1",
|
||||
PublicKey: &PublicKey{
|
||||
PublicKey: []byte("something"),
|
||||
ExpirationDate: time.Date(2024, time.January, 1, 1, 1, 1, 1, time.UTC),
|
||||
},
|
||||
},
|
||||
},
|
||||
res{
|
||||
|
@ -16,6 +16,7 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/id"
|
||||
"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/schemauser"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
@ -23,10 +24,12 @@ import (
|
||||
|
||||
func TestCommands_CreateSchemaUser(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore func(t *testing.T) *eventstore.Eventstore
|
||||
idGenerator id.Generator
|
||||
checkPermission domain.PermissionCheck
|
||||
newCode encrypedCodeFunc
|
||||
eventstore func(t *testing.T) *eventstore.Eventstore
|
||||
idGenerator id.Generator
|
||||
checkPermission domain.PermissionCheck
|
||||
newCode encrypedCodeFunc
|
||||
userPasswordHasher *crypto.Hasher
|
||||
tokenAlg crypto.EncryptionAlgorithm
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
@ -698,15 +701,100 @@ 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 {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
c := &Commands{
|
||||
eventstore: tt.fields.eventstore(t),
|
||||
idGenerator: tt.fields.idGenerator,
|
||||
checkPermission: tt.fields.checkPermission,
|
||||
newEncryptedCode: tt.fields.newCode,
|
||||
userEncryption: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||
eventstore: tt.fields.eventstore(t),
|
||||
idGenerator: tt.fields.idGenerator,
|
||||
checkPermission: tt.fields.checkPermission,
|
||||
newEncryptedCode: tt.fields.newCode,
|
||||
userEncryption: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||
userPasswordHasher: tt.fields.userPasswordHasher,
|
||||
keyAlgorithm: tt.fields.tokenAlg,
|
||||
}
|
||||
details, err := c.CreateSchemaUser(tt.args.ctx, tt.args.user)
|
||||
if tt.res.err == nil {
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
@ -11,18 +12,23 @@ type AddUsername struct {
|
||||
ResourceOwner string
|
||||
UserID string
|
||||
|
||||
Username *Username
|
||||
}
|
||||
|
||||
type Username struct {
|
||||
Username string
|
||||
IsOrgSpecific bool
|
||||
}
|
||||
|
||||
func (c *Commands) AddUsername(ctx context.Context, username *AddUsername) (*domain.ObjectDetails, error) {
|
||||
if username.UserID == "" {
|
||||
func (c *Commands) AddUsername(ctx context.Context, add *AddUsername) (*domain.ObjectDetails, error) {
|
||||
if add.UserID == "" {
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
add.ResourceOwner = schemauser.ResourceOwner
|
||||
|
||||
_, err = existingSchema(ctx, c, "", schemauser.SchemaID)
|
||||
if err != nil {
|
||||
@ -30,21 +36,32 @@ func (c *Commands) AddUsername(ctx context.Context, username *AddUsername) (*dom
|
||||
}
|
||||
// TODO check for possible authenticators
|
||||
|
||||
id, err := c.idGenerator.Next()
|
||||
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)
|
||||
writeModel, events, err := c.addUsername(ctx, add.ResourceOwner, add.UserID, add.Username)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
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) {
|
||||
if userID == "" {
|
||||
return nil, zerrors.ThrowInvalidArgument(nil, "COMMAND-J6ybG5WZiy", "Errors.IDMissing")
|
||||
|
@ -142,6 +142,9 @@ func TestCommands_AddUsername(t *testing.T) {
|
||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||
user: &AddUsername{
|
||||
UserID: "user1",
|
||||
Username: &Username{
|
||||
Username: "user1",
|
||||
},
|
||||
},
|
||||
},
|
||||
res{
|
||||
@ -163,6 +166,9 @@ func TestCommands_AddUsername(t *testing.T) {
|
||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||
user: &AddUsername{
|
||||
UserID: "user1",
|
||||
Username: &Username{
|
||||
Username: "user1",
|
||||
},
|
||||
},
|
||||
},
|
||||
res{
|
||||
@ -194,9 +200,11 @@ func TestCommands_AddUsername(t *testing.T) {
|
||||
args{
|
||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||
user: &AddUsername{
|
||||
UserID: "user1",
|
||||
Username: "username",
|
||||
IsOrgSpecific: false,
|
||||
UserID: "user1",
|
||||
Username: &Username{
|
||||
Username: "username",
|
||||
IsOrgSpecific: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
res{
|
||||
@ -228,9 +236,11 @@ func TestCommands_AddUsername(t *testing.T) {
|
||||
args{
|
||||
ctx: authz.NewMockContext("instanceID", "", ""),
|
||||
user: &AddUsername{
|
||||
UserID: "user1",
|
||||
Username: "username",
|
||||
IsOrgSpecific: true,
|
||||
UserID: "user1",
|
||||
Username: &Username{
|
||||
Username: "username",
|
||||
IsOrgSpecific: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
res{
|
||||
|
Loading…
x
Reference in New Issue
Block a user