mirror of
https://github.com/zitadel/zitadel.git
synced 2025-02-28 12:07:24 +00:00
feat: Config to eventstore (#3158)
* feat: add default language to eventstore * feat: add secret generator configs events * feat: tests * feat: secret generators in eventstore * feat: secret generators in eventstore * feat: smtp config in eventstore * feat: smtp config in eventstore * feat: smtp config in eventstore * feat: smtp config in eventstore * feat: smtp config in eventstore * fix: migrations * fix migration version * fix test * feat: change secret generator type to enum * feat: change smtp attribute names * feat: change smtp attribute names * feat: remove engryption algorithms from command side * feat: remove engryption algorithms from command side * feat: smtp config * feat: smtp config * format smtp from header Co-authored-by: Livio Amstutz <livio.a@gmail.com>
This commit is contained in:
parent
4272ea6fe1
commit
e3528ff0b2
@ -142,6 +142,9 @@ func startZitadel(config *startConfig) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot start eventstore for queries: %w", err)
|
||||
}
|
||||
smtpPasswordCrypto, err := crypto.NewAESCrypto(config.SystemDefaults.SMTPPasswordVerificationKey)
|
||||
logging.Log("MAIN-en9ew").OnError(err).Fatal("cannot create smtp crypto")
|
||||
|
||||
queries, err := query.StartQueries(ctx, eventstoreClient, dbClient, config.Projections.Config, config.SystemDefaults, config.Projections.KeyConfig, keyChan, config.InternalAuthZ.RolePermissionMappings)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot start queries: %w", err)
|
||||
@ -156,12 +159,12 @@ func startZitadel(config *startConfig) error {
|
||||
Origin: http_util.BuildHTTP(config.ExternalDomain, config.ExternalPort, config.ExternalSecure),
|
||||
DisplayName: "ZITADEL",
|
||||
}
|
||||
commands, err := command.StartCommands(eventstoreClient, config.SystemDefaults, config.InternalAuthZ, storage, authZRepo, config.OIDC.KeyConfig, webAuthNConfig)
|
||||
commands, err := command.StartCommands(eventstoreClient, config.SystemDefaults, config.InternalAuthZ, storage, authZRepo, config.OIDC.KeyConfig, smtpPasswordCrypto, webAuthNConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot start commands: %w", err)
|
||||
}
|
||||
|
||||
notification.Start(config.Notification, config.SystemDefaults, commands, queries, dbClient, assets.HandlerPrefix)
|
||||
notification.Start(config.Notification, config.SystemDefaults, commands, queries, dbClient, assets.HandlerPrefix, smtpPasswordCrypto)
|
||||
|
||||
router := mux.NewRouter()
|
||||
err = startAPIs(ctx, router, commands, queries, eventstoreClient, dbClient, keyChan, config, storage, authZRepo)
|
||||
@ -181,9 +184,12 @@ func startAPIs(ctx context.Context, router *mux.Router, commands *command.Comman
|
||||
}
|
||||
verifier := internal_authz.Start(repo)
|
||||
|
||||
apis := api.New(config.Port, router, &repo, config.InternalAuthZ, config.SystemDefaults, config.ExternalSecure)
|
||||
|
||||
authRepo, err := auth_es.Start(config.Auth, config.SystemDefaults, commands, queries, dbClient, config.OIDC.KeyConfig, assets.HandlerPrefix)
|
||||
apis := api.New(config.Port, router, &repo, config.InternalAuthZ, config.ExternalSecure)
|
||||
userEncryptionAlgorithm, err := crypto.NewAESCrypto(config.SystemDefaults.UserVerificationKey)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
authRepo, err := auth_es.Start(config.Auth, config.SystemDefaults, commands, queries, dbClient, config.OIDC.KeyConfig, assets.HandlerPrefix, userEncryptionAlgorithm)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error starting auth repo: %w", err)
|
||||
}
|
||||
@ -191,13 +197,13 @@ func startAPIs(ctx context.Context, router *mux.Router, commands *command.Comman
|
||||
if err != nil {
|
||||
return fmt.Errorf("error starting admin repo: %w", err)
|
||||
}
|
||||
if err := apis.RegisterServer(ctx, admin.CreateServer(commands, queries, adminRepo, config.SystemDefaults.Domain, assets.HandlerPrefix)); err != nil {
|
||||
if err := apis.RegisterServer(ctx, admin.CreateServer(commands, queries, adminRepo, config.SystemDefaults.Domain, assets.HandlerPrefix, userEncryptionAlgorithm)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := apis.RegisterServer(ctx, management.CreateServer(commands, queries, config.SystemDefaults, assets.HandlerPrefix)); err != nil {
|
||||
if err := apis.RegisterServer(ctx, management.CreateServer(commands, queries, config.SystemDefaults, assets.HandlerPrefix, userEncryptionAlgorithm)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := apis.RegisterServer(ctx, auth.CreateServer(commands, queries, authRepo, config.SystemDefaults, assets.HandlerPrefix)); err != nil {
|
||||
if err := apis.RegisterServer(ctx, auth.CreateServer(commands, queries, authRepo, config.SystemDefaults, assets.HandlerPrefix, userEncryptionAlgorithm)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -231,7 +237,7 @@ func startAPIs(ctx context.Context, router *mux.Router, commands *command.Comman
|
||||
}
|
||||
apis.RegisterHandler(console.HandlerPrefix, c)
|
||||
|
||||
l, err := login.CreateLogin(config.Login, commands, queries, authRepo, store, config.SystemDefaults, console.HandlerPrefix, config.ExternalDomain, oidc.AuthCallback, config.ExternalSecure, userAgentInterceptor)
|
||||
l, err := login.CreateLogin(config.Login, commands, queries, authRepo, store, config.SystemDefaults, console.HandlerPrefix, config.ExternalDomain, oidc.AuthCallback, config.ExternalSecure, userAgentInterceptor, userEncryptionAlgorithm)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to start login: %w", err)
|
||||
}
|
||||
|
@ -141,6 +141,8 @@ SystemDefaults:
|
||||
EncryptionKeyID: $ZITADEL_USER_VERIFICATION_KEY
|
||||
IDPConfigVerificationKey:
|
||||
EncryptionKeyID: $ZITADEL_IDP_CONFIG_VERIFICATION_KEY
|
||||
SMTPPasswordVerificationKey:
|
||||
EncryptionKeyID: $ZITADEL_SMTP_PASSWORD_VERIFICATION_KEY
|
||||
SecretGenerators:
|
||||
PasswordSaltCost: 14
|
||||
ClientSecretGenerator:
|
||||
@ -197,7 +199,6 @@ SystemDefaults:
|
||||
MFAInitSkip: 720h #30d
|
||||
SecondFactorCheck: 18h
|
||||
MultiFactorCheck: 12h
|
||||
IamID: 'IAM'
|
||||
DomainVerification:
|
||||
VerificationKey:
|
||||
EncryptionKeyID: $ZITADEL_DOMAIN_VERIFICATION_KEY
|
||||
@ -240,42 +241,6 @@ SystemDefaults:
|
||||
Url: $CHAT_URL
|
||||
# Compact: $CHAT_COMPACT
|
||||
SplitCount: 4000
|
||||
TemplateData:
|
||||
InitCode:
|
||||
Title: 'InitCode.Title'
|
||||
PreHeader: 'InitCode.PreHeader'
|
||||
Subject: 'InitCode.Subject'
|
||||
Greeting: 'InitCode.Greeting'
|
||||
Text: 'InitCode.Text'
|
||||
ButtonText: 'InitCode.ButtonText'
|
||||
PasswordReset:
|
||||
Title: 'PasswordReset.Title'
|
||||
PreHeader: 'PasswordReset.PreHeader'
|
||||
Subject: 'PasswordReset.Subject'
|
||||
Greeting: 'PasswordReset.Greeting'
|
||||
Text: 'PasswordReset.Text'
|
||||
ButtonText: 'PasswordReset.ButtonText'
|
||||
VerifyEmail:
|
||||
Title: 'VerifyEmail.Title'
|
||||
PreHeader: 'VerifyEmail.PreHeader'
|
||||
Subject: 'VerifyEmail.Subject'
|
||||
Greeting: 'VerifyEmail.Greeting'
|
||||
Text: 'VerifyEmail.Text'
|
||||
ButtonText: 'VerifyEmail.ButtonText'
|
||||
VerifyPhone:
|
||||
Title: 'VerifyPhone.Title'
|
||||
PreHeader: 'VerifyPhone.PreHeader'
|
||||
Subject: 'VerifyPhone.Subject'
|
||||
Greeting: 'VerifyPhone.Greeting'
|
||||
Text: 'VerifyPhone.Text'
|
||||
ButtonText: 'VerifyPhone.ButtonText'
|
||||
DomainClaimed:
|
||||
Title: 'DomainClaimed.Title'
|
||||
PreHeader: 'DomainClaimed.PreHeader'
|
||||
Subject: 'DomainClaimed.Subject'
|
||||
Greeting: 'DomainClaimed.Greeting'
|
||||
Text: 'DomainClaimed.Text'
|
||||
ButtonText: 'DomainClaimed.ButtonText'
|
||||
KeyConfig:
|
||||
Size: 2048
|
||||
PrivateKeyLifetime: 6h
|
||||
|
@ -32,6 +32,102 @@ Returns the default languages
|
||||
GET: /languages
|
||||
|
||||
|
||||
### SetDefaultLanguage
|
||||
|
||||
> **rpc** SetDefaultLanguage([SetDefaultLanguageRequest](#setdefaultlanguagerequest))
|
||||
[SetDefaultLanguageResponse](#setdefaultlanguageresponse)
|
||||
|
||||
Set the default language
|
||||
|
||||
|
||||
|
||||
PUT: /languages/default/{language}
|
||||
|
||||
|
||||
### GetDefaultLanguage
|
||||
|
||||
> **rpc** GetDefaultLanguage([GetDefaultLanguageRequest](#getdefaultlanguagerequest))
|
||||
[GetDefaultLanguageResponse](#getdefaultlanguageresponse)
|
||||
|
||||
Set the default language
|
||||
|
||||
|
||||
|
||||
GET: /languages/default
|
||||
|
||||
|
||||
### ListSecretGenerators
|
||||
|
||||
> **rpc** ListSecretGenerators([ListSecretGeneratorsRequest](#listsecretgeneratorsrequest))
|
||||
[ListSecretGeneratorsResponse](#listsecretgeneratorsresponse)
|
||||
|
||||
Set the default language
|
||||
|
||||
|
||||
|
||||
POST: /secretgenerators/_search
|
||||
|
||||
|
||||
### GetSecretGenerator
|
||||
|
||||
> **rpc** GetSecretGenerator([GetSecretGeneratorRequest](#getsecretgeneratorrequest))
|
||||
[GetSecretGeneratorResponse](#getsecretgeneratorresponse)
|
||||
|
||||
Get Secret Generator by type (e.g PasswordResetCode)
|
||||
|
||||
|
||||
|
||||
GET: /secretgenerators/{generator_type}
|
||||
|
||||
|
||||
### UpdateSecretGenerator
|
||||
|
||||
> **rpc** UpdateSecretGenerator([UpdateSecretGeneratorRequest](#updatesecretgeneratorrequest))
|
||||
[UpdateSecretGeneratorResponse](#updatesecretgeneratorresponse)
|
||||
|
||||
Update secret generator configuration
|
||||
|
||||
|
||||
|
||||
PUT: /secretgenerators/{generator_type}
|
||||
|
||||
|
||||
### GetSMTPConfig
|
||||
|
||||
> **rpc** GetSMTPConfig([GetSMTPConfigRequest](#getsmtpconfigrequest))
|
||||
[GetSMTPConfigResponse](#getsmtpconfigresponse)
|
||||
|
||||
Get system smtp configuration
|
||||
|
||||
|
||||
|
||||
GET: /smtp
|
||||
|
||||
|
||||
### UpdateSMTPConfig
|
||||
|
||||
> **rpc** UpdateSMTPConfig([UpdateSMTPConfigRequest](#updatesmtpconfigrequest))
|
||||
[UpdateSMTPConfigResponse](#updatesmtpconfigresponse)
|
||||
|
||||
Update system smtp configuration
|
||||
|
||||
|
||||
|
||||
PUT: /smtp
|
||||
|
||||
|
||||
### UpdateSMTPConfigPassword
|
||||
|
||||
> **rpc** UpdateSMTPConfigPassword([UpdateSMTPConfigPasswordRequest](#updatesmtpconfigpasswordrequest))
|
||||
[UpdateSMTPConfigPasswordResponse](#updatesmtpconfigpasswordresponse)
|
||||
|
||||
Update system smtp configuration password for host
|
||||
|
||||
|
||||
|
||||
PUT: /smtp/password
|
||||
|
||||
|
||||
### GetOrgByID
|
||||
|
||||
> **rpc** GetOrgByID([GetOrgByIDRequest](#getorgbyidrequest))
|
||||
@ -1665,6 +1761,23 @@ This is an empty response
|
||||
|
||||
|
||||
|
||||
### GetDefaultLanguageRequest
|
||||
This is an empty request
|
||||
|
||||
|
||||
|
||||
|
||||
### GetDefaultLanguageResponse
|
||||
|
||||
|
||||
|
||||
| Field | Type | Description | Validation |
|
||||
| ----- | ---- | ----------- | ----------- |
|
||||
| language | string | - | |
|
||||
|
||||
|
||||
|
||||
|
||||
### GetDefaultLoginTextsRequest
|
||||
|
||||
|
||||
@ -1977,6 +2090,45 @@ This is an empty request
|
||||
|
||||
|
||||
|
||||
### GetSMTPConfigRequest
|
||||
This is an empty request
|
||||
|
||||
|
||||
|
||||
|
||||
### GetSMTPConfigResponse
|
||||
|
||||
|
||||
|
||||
| Field | Type | Description | Validation |
|
||||
| ----- | ---- | ----------- | ----------- |
|
||||
| smtp_config | zitadel.settings.v1.SMTPConfig | - | |
|
||||
|
||||
|
||||
|
||||
|
||||
### GetSecretGeneratorRequest
|
||||
|
||||
|
||||
|
||||
| Field | Type | Description | Validation |
|
||||
| ----- | ---- | ----------- | ----------- |
|
||||
| generator_type | zitadel.settings.v1.SecretGeneratorType | - | enum.defined_only: true<br /> enum.not_in: [0]<br /> |
|
||||
|
||||
|
||||
|
||||
|
||||
### GetSecretGeneratorResponse
|
||||
|
||||
|
||||
|
||||
| Field | Type | Description | Validation |
|
||||
| ----- | ---- | ----------- | ----------- |
|
||||
| secret_generator | zitadel.settings.v1.SecretGenerator | - | |
|
||||
|
||||
|
||||
|
||||
|
||||
### GetSupportedLanguagesRequest
|
||||
This is an empty request
|
||||
|
||||
@ -2211,6 +2363,30 @@ This is an empty request
|
||||
|
||||
|
||||
|
||||
### ListSecretGeneratorsRequest
|
||||
|
||||
|
||||
|
||||
| Field | Type | Description | Validation |
|
||||
| ----- | ---- | ----------- | ----------- |
|
||||
| query | zitadel.v1.ListQuery | list limitations and ordering | |
|
||||
| queries | repeated zitadel.settings.v1.SecretGeneratorQuery | criterias the client is looking for | |
|
||||
|
||||
|
||||
|
||||
|
||||
### ListSecretGeneratorsResponse
|
||||
|
||||
|
||||
|
||||
| Field | Type | Description | Validation |
|
||||
| ----- | ---- | ----------- | ----------- |
|
||||
| details | zitadel.v1.ListDetails | - | |
|
||||
| result | repeated zitadel.settings.v1.SecretGenerator | - | |
|
||||
|
||||
|
||||
|
||||
|
||||
### ListViewsRequest
|
||||
This is an empty request
|
||||
|
||||
@ -2820,6 +2996,28 @@ This is an empty request
|
||||
|
||||
|
||||
|
||||
### SetDefaultLanguageRequest
|
||||
|
||||
|
||||
|
||||
| Field | Type | Description | Validation |
|
||||
| ----- | ---- | ----------- | ----------- |
|
||||
| language | string | - | string.min_len: 1<br /> string.max_len: 10<br /> |
|
||||
|
||||
|
||||
|
||||
|
||||
### SetDefaultLanguageResponse
|
||||
|
||||
|
||||
|
||||
| Field | Type | Description | Validation |
|
||||
| ----- | ---- | ----------- | ----------- |
|
||||
| details | zitadel.v1.ObjectDetails | - | |
|
||||
|
||||
|
||||
|
||||
|
||||
### SetDefaultPasswordResetMessageTextRequest
|
||||
|
||||
|
||||
@ -3374,6 +3572,82 @@ This is an empty request
|
||||
|
||||
|
||||
|
||||
### UpdateSMTPConfigPasswordRequest
|
||||
|
||||
|
||||
|
||||
| Field | Type | Description | Validation |
|
||||
| ----- | ---- | ----------- | ----------- |
|
||||
| password | string | - | |
|
||||
|
||||
|
||||
|
||||
|
||||
### UpdateSMTPConfigPasswordResponse
|
||||
|
||||
|
||||
|
||||
| Field | Type | Description | Validation |
|
||||
| ----- | ---- | ----------- | ----------- |
|
||||
| details | zitadel.v1.ObjectDetails | - | |
|
||||
|
||||
|
||||
|
||||
|
||||
### UpdateSMTPConfigRequest
|
||||
|
||||
|
||||
|
||||
| Field | Type | Description | Validation |
|
||||
| ----- | ---- | ----------- | ----------- |
|
||||
| sender_address | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
|
||||
| sender_name | string | - | string.min_len: 1<br /> string.max_len: 200<br /> |
|
||||
| tls | bool | - | |
|
||||
| host | string | - | string.min_len: 1<br /> string.max_len: 500<br /> |
|
||||
| user | string | - | |
|
||||
|
||||
|
||||
|
||||
|
||||
### UpdateSMTPConfigResponse
|
||||
|
||||
|
||||
|
||||
| Field | Type | Description | Validation |
|
||||
| ----- | ---- | ----------- | ----------- |
|
||||
| details | zitadel.v1.ObjectDetails | - | |
|
||||
|
||||
|
||||
|
||||
|
||||
### UpdateSecretGeneratorRequest
|
||||
|
||||
|
||||
|
||||
| Field | Type | Description | Validation |
|
||||
| ----- | ---- | ----------- | ----------- |
|
||||
| generator_type | zitadel.settings.v1.SecretGeneratorType | - | enum.defined_only: true<br /> enum.not_in: [0]<br /> |
|
||||
| length | uint32 | - | |
|
||||
| expiry | google.protobuf.Duration | - | |
|
||||
| include_lower_letters | bool | - | |
|
||||
| include_upper_letters | bool | - | |
|
||||
| include_digits | bool | - | |
|
||||
| include_symbols | bool | - | |
|
||||
|
||||
|
||||
|
||||
|
||||
### UpdateSecretGeneratorResponse
|
||||
|
||||
|
||||
|
||||
| Field | Type | Description | Validation |
|
||||
| ----- | ---- | ----------- | ----------- |
|
||||
| details | zitadel.v1.ObjectDetails | - | |
|
||||
|
||||
|
||||
|
||||
|
||||
### View
|
||||
|
||||
|
||||
|
2
go.mod
2
go.mod
@ -44,7 +44,6 @@ require (
|
||||
github.com/pquerna/otp v1.3.0
|
||||
github.com/rakyll/statik v0.1.7
|
||||
github.com/rs/cors v1.8.0
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
github.com/sony/sonyflake v1.0.0
|
||||
github.com/spf13/cobra v1.3.0
|
||||
github.com/spf13/viper v1.10.1
|
||||
@ -140,6 +139,7 @@ require (
|
||||
github.com/prometheus/procfs v0.6.0 // indirect
|
||||
github.com/rs/xid v1.2.1 // indirect
|
||||
github.com/satori/go.uuid v1.2.0 // indirect
|
||||
github.com/sirupsen/logrus v1.8.1 // indirect
|
||||
github.com/spf13/afero v1.8.1 // indirect
|
||||
github.com/spf13/cast v1.4.1 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
|
2
go.sum
2
go.sum
@ -124,8 +124,6 @@ github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBW
|
||||
github.com/boombuler/barcode v1.0.1 h1:NDBbPmhS+EqABEs5Kg3n/5ZNjy73Pz7SIV+KCeqyXcs=
|
||||
github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||
github.com/caos/logging v0.0.2/go.mod h1:9LKiDE2ChuGv6CHYif/kiugrfEXu9AwDiFWSreX7Wp0=
|
||||
github.com/caos/logging v0.3.0 h1:PMKd47Aqr98FjAPcAE8v3SCe8eqTEclytruND/zc7QU=
|
||||
github.com/caos/logging v0.3.0/go.mod h1:B8QNS0WDmR2Keac52Fw+XN4ZJkzLDGrcRIPB2Ux4uRo=
|
||||
github.com/caos/logging v0.3.1 h1:892AMeHs09D0e3ZcGB+QDRsZ5+2xtPAsAhOy8eKfztc=
|
||||
github.com/caos/logging v0.3.1/go.mod h1:B8QNS0WDmR2Keac52Fw+XN4ZJkzLDGrcRIPB2Ux4uRo=
|
||||
github.com/caos/oidc v1.0.1 h1:8UHAPynCObwaqortppDtJFktjqLDLYSLidkNy0Num4o=
|
||||
|
@ -15,7 +15,6 @@ import (
|
||||
"github.com/caos/zitadel/internal/api/grpc/server"
|
||||
http_util "github.com/caos/zitadel/internal/api/http"
|
||||
"github.com/caos/zitadel/internal/authz/repository"
|
||||
"github.com/caos/zitadel/internal/config/systemdefaults"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/query"
|
||||
@ -44,7 +43,6 @@ func New(
|
||||
*query.Queries
|
||||
},
|
||||
authZ internal_authz.Config,
|
||||
sd systemdefaults.SystemDefaults,
|
||||
externalSecure bool,
|
||||
) *API {
|
||||
verifier := internal_authz.Start(repo)
|
||||
@ -55,7 +53,7 @@ func New(
|
||||
router: router,
|
||||
externalSecure: externalSecure,
|
||||
}
|
||||
api.grpcServer = server.CreateServer(api.verifier, authZ, sd.DefaultLanguage)
|
||||
api.grpcServer = server.CreateServer(api.verifier, authZ, repo.Queries)
|
||||
api.routeGRPC()
|
||||
|
||||
api.RegisterHandler("/debug", api.healthHandler())
|
||||
|
82
internal/api/grpc/admin/iam_settings.go
Normal file
82
internal/api/grpc/admin/iam_settings.go
Normal file
@ -0,0 +1,82 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/api/grpc/object"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
admin_pb "github.com/caos/zitadel/pkg/grpc/admin"
|
||||
)
|
||||
|
||||
func (s *Server) ListSecretGenerators(ctx context.Context, req *admin_pb.ListSecretGeneratorsRequest) (*admin_pb.ListSecretGeneratorsResponse, error) {
|
||||
queries, err := listSecretGeneratorToModel(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result, err := s.query.SearchSecretGenerators(ctx, queries)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.ListSecretGeneratorsResponse{
|
||||
Details: object.ToListDetails(result.Count, result.Sequence, result.Timestamp),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) GetSecretGenerator(ctx context.Context, req *admin_pb.GetSecretGeneratorRequest) (*admin_pb.GetSecretGeneratorResponse, error) {
|
||||
generator, err := s.query.SecretGeneratorByType(ctx, SecretGeneratorTypeToDomain(req.GeneratorType))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.GetSecretGeneratorResponse{
|
||||
SecretGenerator: SecretGeneratorToPb(generator),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) UpdateSecretGenerator(ctx context.Context, req *admin_pb.UpdateSecretGeneratorRequest) (*admin_pb.UpdateSecretGeneratorResponse, error) {
|
||||
details, err := s.command.ChangeSecretGeneratorConfig(ctx, SecretGeneratorTypeToDomain(req.GeneratorType), UpdateSecretGeneratorToConfig(req))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.UpdateSecretGeneratorResponse{
|
||||
Details: object.ChangeToDetailsPb(
|
||||
details.Sequence,
|
||||
details.EventDate,
|
||||
details.ResourceOwner),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) GetSMTPConfig(ctx context.Context, req *admin_pb.GetSMTPConfigRequest) (*admin_pb.GetSMTPConfigResponse, error) {
|
||||
smtp, err := s.query.SMTPConfigByAggregateID(ctx, domain.IAMID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.GetSMTPConfigResponse{
|
||||
SmtpConfig: SMTPConfigToPb(smtp),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) UpdateSMTPConfig(ctx context.Context, req *admin_pb.UpdateSMTPConfigRequest) (*admin_pb.UpdateSMTPConfigResponse, error) {
|
||||
details, err := s.command.ChangeSMTPConfig(ctx, UpdateSMTPToConfig(req))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.UpdateSMTPConfigResponse{
|
||||
Details: object.ChangeToDetailsPb(
|
||||
details.Sequence,
|
||||
details.EventDate,
|
||||
details.ResourceOwner),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) UpdateSMTPConfigPassword(ctx context.Context, req *admin_pb.UpdateSMTPConfigPasswordRequest) (*admin_pb.UpdateSMTPConfigPasswordResponse, error) {
|
||||
details, err := s.command.ChangeSMTPConfigPassword(ctx, req.Password)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.UpdateSMTPConfigPasswordResponse{
|
||||
Details: object.ChangeToDetailsPb(
|
||||
details.Sequence,
|
||||
details.EventDate,
|
||||
details.ResourceOwner),
|
||||
}, nil
|
||||
}
|
138
internal/api/grpc/admin/iam_settings_converter.go
Normal file
138
internal/api/grpc/admin/iam_settings_converter.go
Normal file
@ -0,0 +1,138 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"google.golang.org/protobuf/types/known/durationpb"
|
||||
|
||||
"github.com/caos/zitadel/internal/api/grpc/object"
|
||||
obj_grpc "github.com/caos/zitadel/internal/api/grpc/object"
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/notification/channels/smtp"
|
||||
"github.com/caos/zitadel/internal/query"
|
||||
admin_pb "github.com/caos/zitadel/pkg/grpc/admin"
|
||||
settings_pb "github.com/caos/zitadel/pkg/grpc/settings"
|
||||
)
|
||||
|
||||
func listSecretGeneratorToModel(req *admin_pb.ListSecretGeneratorsRequest) (*query.SecretGeneratorSearchQueries, error) {
|
||||
offset, limit, asc := object.ListQueryToModel(req.Query)
|
||||
queries, err := SecretGeneratorQueriesToModel(req.Queries)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &query.SecretGeneratorSearchQueries{
|
||||
SearchRequest: query.SearchRequest{
|
||||
Offset: offset,
|
||||
Limit: limit,
|
||||
Asc: asc,
|
||||
},
|
||||
Queries: queries,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func SecretGeneratorQueriesToModel(queries []*settings_pb.SecretGeneratorQuery) (_ []query.SearchQuery, err error) {
|
||||
q := make([]query.SearchQuery, len(queries))
|
||||
for i, query := range queries {
|
||||
q[i], err = SecretGeneratorQueryToModel(query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func SecretGeneratorQueryToModel(apiQuery *settings_pb.SecretGeneratorQuery) (query.SearchQuery, error) {
|
||||
switch q := apiQuery.Query.(type) {
|
||||
case *settings_pb.SecretGeneratorQuery_TypeQuery:
|
||||
domainType := SecretGeneratorTypeToDomain(q.TypeQuery.GeneratorType)
|
||||
return query.NewSecretGeneratorTypeSearchQuery(int32(domainType))
|
||||
default:
|
||||
return nil, errors.ThrowInvalidArgument(nil, "ORG-fm9es", "List.Query.Invalid")
|
||||
}
|
||||
}
|
||||
|
||||
func UpdateSecretGeneratorToConfig(req *admin_pb.UpdateSecretGeneratorRequest) *crypto.GeneratorConfig {
|
||||
return &crypto.GeneratorConfig{
|
||||
Length: uint(req.Length),
|
||||
Expiry: req.Expiry.AsDuration(),
|
||||
IncludeUpperLetters: req.IncludeUpperLetters,
|
||||
IncludeLowerLetters: req.IncludeLowerLetters,
|
||||
IncludeDigits: req.IncludeDigits,
|
||||
IncludeSymbols: req.IncludeSymbols,
|
||||
}
|
||||
}
|
||||
|
||||
func SecretGeneratorToPb(generator *query.SecretGenerator) *settings_pb.SecretGenerator {
|
||||
mapped := &settings_pb.SecretGenerator{
|
||||
Length: uint32(generator.Length),
|
||||
Expiry: durationpb.New(generator.Expiry),
|
||||
IncludeUpperLetters: generator.IncludeUpperLetters,
|
||||
IncludeLowerLetters: generator.IncludeLowerLetters,
|
||||
IncludeDigits: generator.IncludeDigits,
|
||||
IncludeSymbols: generator.IncludeSymbols,
|
||||
Details: obj_grpc.ToViewDetailsPb(generator.Sequence, generator.CreationDate, generator.ChangeDate, generator.AggregateID),
|
||||
}
|
||||
return mapped
|
||||
}
|
||||
|
||||
func SecretGeneratorTypeToPb(generatorType domain.SecretGeneratorType) settings_pb.SecretGeneratorType {
|
||||
switch generatorType {
|
||||
case domain.SecretGeneratorTypeInitCode:
|
||||
return settings_pb.SecretGeneratorType_SECRET_GENERATOR_TYPE_INIT_CODE
|
||||
case domain.SecretGeneratorTypeVerifyEmailCode:
|
||||
return settings_pb.SecretGeneratorType_SECRET_GENERATOR_TYPE_VERIFY_EMAIL_CODE
|
||||
case domain.SecretGeneratorTypeVerifyPhoneCode:
|
||||
return settings_pb.SecretGeneratorType_SECRET_GENERATOR_TYPE_VERIFY_PHONE_CODE
|
||||
case domain.SecretGeneratorTypePasswordResetCode:
|
||||
return settings_pb.SecretGeneratorType_SECRET_GENERATOR_TYPE_PASSWORD_RESET_CODE
|
||||
case domain.SecretGeneratorTypePasswordlessInitCode:
|
||||
return settings_pb.SecretGeneratorType_SECRET_GENERATOR_TYPE_PASSWORDLESS_INIT_CODE
|
||||
case domain.SecretGeneratorTypeAppSecret:
|
||||
return settings_pb.SecretGeneratorType_SECRET_GENERATOR_TYPE_APP_SECRET
|
||||
default:
|
||||
return settings_pb.SecretGeneratorType_SECRET_GENERATOR_TYPE_UNSPECIFIED
|
||||
}
|
||||
}
|
||||
|
||||
func SecretGeneratorTypeToDomain(generatorType settings_pb.SecretGeneratorType) domain.SecretGeneratorType {
|
||||
switch generatorType {
|
||||
case settings_pb.SecretGeneratorType_SECRET_GENERATOR_TYPE_INIT_CODE:
|
||||
return domain.SecretGeneratorTypeInitCode
|
||||
case settings_pb.SecretGeneratorType_SECRET_GENERATOR_TYPE_VERIFY_EMAIL_CODE:
|
||||
return domain.SecretGeneratorTypeVerifyEmailCode
|
||||
case settings_pb.SecretGeneratorType_SECRET_GENERATOR_TYPE_VERIFY_PHONE_CODE:
|
||||
return domain.SecretGeneratorTypeVerifyPhoneCode
|
||||
case settings_pb.SecretGeneratorType_SECRET_GENERATOR_TYPE_PASSWORD_RESET_CODE:
|
||||
return domain.SecretGeneratorTypePasswordResetCode
|
||||
case settings_pb.SecretGeneratorType_SECRET_GENERATOR_TYPE_PASSWORDLESS_INIT_CODE:
|
||||
return domain.SecretGeneratorTypePasswordlessInitCode
|
||||
case settings_pb.SecretGeneratorType_SECRET_GENERATOR_TYPE_APP_SECRET:
|
||||
return domain.SecretGeneratorTypeAppSecret
|
||||
default:
|
||||
return domain.SecretGeneratorTypeUnspecified
|
||||
}
|
||||
}
|
||||
|
||||
func UpdateSMTPToConfig(req *admin_pb.UpdateSMTPConfigRequest) *smtp.EmailConfig {
|
||||
return &smtp.EmailConfig{
|
||||
Tls: req.Tls,
|
||||
From: req.SenderAddress,
|
||||
FromName: req.SenderName,
|
||||
SMTP: smtp.SMTP{
|
||||
Host: req.Host,
|
||||
User: req.User,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func SMTPConfigToPb(smtp *query.SMTPConfig) *settings_pb.SMTPConfig {
|
||||
mapped := &settings_pb.SMTPConfig{
|
||||
Tls: smtp.TLS,
|
||||
SenderAddress: smtp.SenderAddress,
|
||||
SenderName: smtp.SenderName,
|
||||
Host: smtp.Host,
|
||||
User: smtp.User,
|
||||
Details: obj_grpc.ToViewDetailsPb(smtp.Sequence, smtp.CreationDate, smtp.ChangeDate, smtp.AggregateID),
|
||||
}
|
||||
return mapped
|
||||
}
|
@ -3,8 +3,12 @@ package admin
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/api/grpc/object"
|
||||
"github.com/caos/zitadel/internal/api/grpc/text"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
caos_errors "github.com/caos/zitadel/internal/errors"
|
||||
admin_pb "github.com/caos/zitadel/pkg/grpc/admin"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
func (s *Server) GetSupportedLanguages(ctx context.Context, req *admin_pb.GetSupportedLanguagesRequest) (*admin_pb.GetSupportedLanguagesResponse, error) {
|
||||
@ -14,3 +18,25 @@ func (s *Server) GetSupportedLanguages(ctx context.Context, req *admin_pb.GetSup
|
||||
}
|
||||
return &admin_pb.GetSupportedLanguagesResponse{Languages: text.LanguageTagsToStrings(langs)}, nil
|
||||
}
|
||||
|
||||
func (s *Server) SetDefaultLanguage(ctx context.Context, req *admin_pb.SetDefaultLanguageRequest) (*admin_pb.SetDefaultLanguageResponse, error) {
|
||||
lang, err := language.Parse(req.Language)
|
||||
if err != nil {
|
||||
return nil, caos_errors.ThrowInvalidArgument(err, "API-39nnf", "Errors.Language.Parse")
|
||||
}
|
||||
details, err := s.command.SetDefaultLanguage(ctx, lang)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.SetDefaultLanguageResponse{
|
||||
Details: object.DomainToChangeDetailsPb(details),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) GetDefaultLanguage(ctx context.Context, req *admin_pb.GetDefaultLanguageRequest) (*admin_pb.GetDefaultLanguageResponse, error) {
|
||||
iam, err := s.query.IAMByID(ctx, domain.IAMID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.GetDefaultLanguageResponse{Language: iam.DefaultLanguage.String()}, nil
|
||||
}
|
||||
|
@ -53,7 +53,15 @@ func (s *Server) SetUpOrg(ctx context.Context, req *admin_pb.SetUpOrgRequest) (*
|
||||
human := setUpOrgHumanToDomain(req.User.(*admin_pb.SetUpOrgRequest_Human_).Human) //TODO: handle machine
|
||||
org := setUpOrgOrgToDomain(req.Org)
|
||||
|
||||
objectDetails, err := s.command.SetUpOrg(ctx, org, human, userIDs, false)
|
||||
initCodeGenerator, err := s.query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypeInitCode, s.UserCodeAlg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
phoneCodeGenerator, err := s.query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypeVerifyPhoneCode, s.UserCodeAlg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
objectDetails, err := s.command.SetUpOrg(ctx, org, human, initCodeGenerator, phoneCodeGenerator, userIDs, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"google.golang.org/grpc"
|
||||
|
||||
"github.com/caos/zitadel/internal/admin/repository"
|
||||
@ -25,19 +26,22 @@ type Server struct {
|
||||
administrator repository.AdministratorRepository
|
||||
iamDomain string
|
||||
assetsAPIDomain string
|
||||
|
||||
UserCodeAlg crypto.EncryptionAlgorithm
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Repository eventsourcing.Config
|
||||
}
|
||||
|
||||
func CreateServer(command *command.Commands, query *query.Queries, repo repository.Repository, iamDomain, assetsAPIDomain string) *Server {
|
||||
func CreateServer(command *command.Commands, query *query.Queries, repo repository.Repository, iamDomain, assetsAPIDomain string, userCrypto *crypto.AESCrypto) *Server {
|
||||
return &Server{
|
||||
command: command,
|
||||
query: query,
|
||||
administrator: repo,
|
||||
iamDomain: iamDomain,
|
||||
assetsAPIDomain: assetsAPIDomain,
|
||||
UserCodeAlg: userCrypto,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"github.com/caos/zitadel/internal/api/authz"
|
||||
"github.com/caos/zitadel/internal/api/grpc/object"
|
||||
"github.com/caos/zitadel/internal/api/grpc/user"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
auth_pb "github.com/caos/zitadel/pkg/grpc/auth"
|
||||
)
|
||||
|
||||
@ -26,7 +27,11 @@ func (s *Server) GetMyEmail(ctx context.Context, _ *auth_pb.GetMyEmailRequest) (
|
||||
}
|
||||
|
||||
func (s *Server) SetMyEmail(ctx context.Context, req *auth_pb.SetMyEmailRequest) (*auth_pb.SetMyEmailResponse, error) {
|
||||
email, err := s.command.ChangeHumanEmail(ctx, UpdateMyEmailToDomain(ctx, req))
|
||||
emailCodeGenerator, err := s.query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypeVerifyEmailCode, s.UserCodeAlg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
email, err := s.command.ChangeHumanEmail(ctx, UpdateMyEmailToDomain(ctx, req), emailCodeGenerator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -40,8 +45,12 @@ func (s *Server) SetMyEmail(ctx context.Context, req *auth_pb.SetMyEmailRequest)
|
||||
}
|
||||
|
||||
func (s *Server) VerifyMyEmail(ctx context.Context, req *auth_pb.VerifyMyEmailRequest) (*auth_pb.VerifyMyEmailResponse, error) {
|
||||
emailCodeGenerator, err := s.query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypeVerifyEmailCode, s.UserCodeAlg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ctxData := authz.GetCtxData(ctx)
|
||||
objectDetails, err := s.command.VerifyHumanEmail(ctx, ctxData.UserID, req.Code, ctxData.ResourceOwner)
|
||||
objectDetails, err := s.command.VerifyHumanEmail(ctx, ctxData.UserID, req.Code, ctxData.ResourceOwner, emailCodeGenerator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -52,7 +61,11 @@ func (s *Server) VerifyMyEmail(ctx context.Context, req *auth_pb.VerifyMyEmailRe
|
||||
|
||||
func (s *Server) ResendMyEmailVerification(ctx context.Context, _ *auth_pb.ResendMyEmailVerificationRequest) (*auth_pb.ResendMyEmailVerificationResponse, error) {
|
||||
ctxData := authz.GetCtxData(ctx)
|
||||
objectDetails, err := s.command.CreateHumanEmailVerificationCode(ctx, ctxData.UserID, ctxData.ResourceOwner)
|
||||
emailCodeGenerator, err := s.query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypeVerifyEmailCode, s.UserCodeAlg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
objectDetails, err := s.command.CreateHumanEmailVerificationCode(ctx, ctxData.UserID, ctxData.ResourceOwner, emailCodeGenerator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -57,7 +57,11 @@ func (s *Server) AddMyPasswordless(ctx context.Context, _ *auth_pb.AddMyPassword
|
||||
|
||||
func (s *Server) AddMyPasswordlessLink(ctx context.Context, _ *auth_pb.AddMyPasswordlessLinkRequest) (*auth_pb.AddMyPasswordlessLinkResponse, error) {
|
||||
ctxData := authz.GetCtxData(ctx)
|
||||
initCode, err := s.command.HumanAddPasswordlessInitCode(ctx, ctxData.UserID, ctxData.ResourceOwner)
|
||||
passwordlessInitCode, err := s.query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypePasswordlessInitCode, s.UserCodeAlg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
initCode, err := s.command.HumanAddPasswordlessInitCode(ctx, ctxData.UserID, ctxData.ResourceOwner, passwordlessInitCode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -70,7 +74,11 @@ func (s *Server) AddMyPasswordlessLink(ctx context.Context, _ *auth_pb.AddMyPass
|
||||
|
||||
func (s *Server) SendMyPasswordlessLink(ctx context.Context, _ *auth_pb.SendMyPasswordlessLinkRequest) (*auth_pb.SendMyPasswordlessLinkResponse, error) {
|
||||
ctxData := authz.GetCtxData(ctx)
|
||||
initCode, err := s.command.HumanSendPasswordlessInitCode(ctx, ctxData.UserID, ctxData.ResourceOwner)
|
||||
passwordlessInitCode, err := s.query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypePasswordlessInitCode, s.UserCodeAlg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
initCode, err := s.command.HumanSendPasswordlessInitCode(ctx, ctxData.UserID, ctxData.ResourceOwner, passwordlessInitCode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"github.com/caos/zitadel/internal/api/authz"
|
||||
"github.com/caos/zitadel/internal/api/grpc/object"
|
||||
"github.com/caos/zitadel/internal/api/grpc/user"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
auth_pb "github.com/caos/zitadel/pkg/grpc/auth"
|
||||
)
|
||||
|
||||
@ -26,7 +27,11 @@ func (s *Server) GetMyPhone(ctx context.Context, _ *auth_pb.GetMyPhoneRequest) (
|
||||
}
|
||||
|
||||
func (s *Server) SetMyPhone(ctx context.Context, req *auth_pb.SetMyPhoneRequest) (*auth_pb.SetMyPhoneResponse, error) {
|
||||
phone, err := s.command.ChangeHumanPhone(ctx, UpdateMyPhoneToDomain(ctx, req), authz.GetCtxData(ctx).ResourceOwner)
|
||||
phoneCodeGenerator, err := s.query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypeVerifyPhoneCode, s.UserCodeAlg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
phone, err := s.command.ChangeHumanPhone(ctx, UpdateMyPhoneToDomain(ctx, req), authz.GetCtxData(ctx).ResourceOwner, phoneCodeGenerator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -41,7 +46,11 @@ func (s *Server) SetMyPhone(ctx context.Context, req *auth_pb.SetMyPhoneRequest)
|
||||
|
||||
func (s *Server) VerifyMyPhone(ctx context.Context, req *auth_pb.VerifyMyPhoneRequest) (*auth_pb.VerifyMyPhoneResponse, error) {
|
||||
ctxData := authz.GetCtxData(ctx)
|
||||
objectDetails, err := s.command.VerifyHumanPhone(ctx, ctxData.UserID, req.Code, ctxData.ResourceOwner)
|
||||
phoneCodeGenerator, err := s.query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypeVerifyPhoneCode, s.UserCodeAlg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
objectDetails, err := s.command.VerifyHumanPhone(ctx, ctxData.UserID, req.Code, ctxData.ResourceOwner, phoneCodeGenerator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -53,7 +62,11 @@ func (s *Server) VerifyMyPhone(ctx context.Context, req *auth_pb.VerifyMyPhoneRe
|
||||
|
||||
func (s *Server) ResendMyPhoneVerification(ctx context.Context, _ *auth_pb.ResendMyPhoneVerificationRequest) (*auth_pb.ResendMyPhoneVerificationResponse, error) {
|
||||
ctxData := authz.GetCtxData(ctx)
|
||||
objectDetails, err := s.command.CreateHumanPhoneVerificationCode(ctx, ctxData.UserID, ctxData.ResourceOwner)
|
||||
phoneCodeGenerator, err := s.query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypeVerifyPhoneCode, s.UserCodeAlg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
objectDetails, err := s.command.CreateHumanPhoneVerificationCode(ctx, ctxData.UserID, ctxData.ResourceOwner, phoneCodeGenerator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"google.golang.org/grpc"
|
||||
|
||||
"github.com/caos/zitadel/internal/api/authz"
|
||||
@ -26,19 +27,21 @@ type Server struct {
|
||||
repo repository.Repository
|
||||
defaults systemdefaults.SystemDefaults
|
||||
assetsAPIDomain string
|
||||
UserCodeAlg crypto.EncryptionAlgorithm
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Repository eventsourcing.Config
|
||||
}
|
||||
|
||||
func CreateServer(command *command.Commands, query *query.Queries, authRepo repository.Repository, defaults systemdefaults.SystemDefaults, assetsAPIDomain string) *Server {
|
||||
func CreateServer(command *command.Commands, query *query.Queries, authRepo repository.Repository, defaults systemdefaults.SystemDefaults, assetsAPIDomain string, userCrypto *crypto.AESCrypto) *Server {
|
||||
return &Server{
|
||||
command: command,
|
||||
query: query,
|
||||
repo: authRepo,
|
||||
defaults: defaults,
|
||||
assetsAPIDomain: assetsAPIDomain,
|
||||
UserCodeAlg: userCrypto,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,11 +3,12 @@ package management
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
mgmt_pb "github.com/caos/zitadel/pkg/grpc/management"
|
||||
)
|
||||
|
||||
func (s *Server) GetIAM(ctx context.Context, req *mgmt_pb.GetIAMRequest) (*mgmt_pb.GetIAMResponse, error) {
|
||||
iam, err := s.query.IAMByID(ctx, s.systemDefaults.IamID)
|
||||
iam, err := s.query.IAMByID(ctx, domain.IAMID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
change_grpc "github.com/caos/zitadel/internal/api/grpc/change"
|
||||
object_grpc "github.com/caos/zitadel/internal/api/grpc/object"
|
||||
project_grpc "github.com/caos/zitadel/internal/api/grpc/project"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"github.com/caos/zitadel/internal/query"
|
||||
mgmt_pb "github.com/caos/zitadel/pkg/grpc/management"
|
||||
)
|
||||
@ -57,7 +58,11 @@ func (s *Server) ListAppChanges(ctx context.Context, req *mgmt_pb.ListAppChanges
|
||||
}
|
||||
|
||||
func (s *Server) AddOIDCApp(ctx context.Context, req *mgmt_pb.AddOIDCAppRequest) (*mgmt_pb.AddOIDCAppResponse, error) {
|
||||
app, err := s.command.AddOIDCApplication(ctx, AddOIDCAppRequestToDomain(req), authz.GetCtxData(ctx).OrgID)
|
||||
appSecretGenerator, err := s.query.InitHashGenerator(ctx, domain.SecretGeneratorTypeAppSecret, s.PasswordHashAlg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
app, err := s.command.AddOIDCApplication(ctx, AddOIDCAppRequestToDomain(req), authz.GetCtxData(ctx).OrgID, appSecretGenerator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -72,7 +77,11 @@ func (s *Server) AddOIDCApp(ctx context.Context, req *mgmt_pb.AddOIDCAppRequest)
|
||||
}
|
||||
|
||||
func (s *Server) AddAPIApp(ctx context.Context, req *mgmt_pb.AddAPIAppRequest) (*mgmt_pb.AddAPIAppResponse, error) {
|
||||
app, err := s.command.AddAPIApplication(ctx, AddAPIAppRequestToDomain(req), authz.GetCtxData(ctx).OrgID)
|
||||
appSecretGenerator, err := s.query.InitHashGenerator(ctx, domain.SecretGeneratorTypeAppSecret, s.PasswordHashAlg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
app, err := s.command.AddAPIApplication(ctx, AddAPIAppRequestToDomain(req), authz.GetCtxData(ctx).OrgID, appSecretGenerator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -153,7 +162,11 @@ func (s *Server) RemoveApp(ctx context.Context, req *mgmt_pb.RemoveAppRequest) (
|
||||
}
|
||||
|
||||
func (s *Server) RegenerateOIDCClientSecret(ctx context.Context, req *mgmt_pb.RegenerateOIDCClientSecretRequest) (*mgmt_pb.RegenerateOIDCClientSecretResponse, error) {
|
||||
config, err := s.command.ChangeOIDCApplicationSecret(ctx, req.ProjectId, req.AppId, authz.GetCtxData(ctx).OrgID)
|
||||
appSecretGenerator, err := s.query.InitHashGenerator(ctx, domain.SecretGeneratorTypeAppSecret, s.PasswordHashAlg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config, err := s.command.ChangeOIDCApplicationSecret(ctx, req.ProjectId, req.AppId, authz.GetCtxData(ctx).OrgID, appSecretGenerator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -168,7 +181,11 @@ func (s *Server) RegenerateOIDCClientSecret(ctx context.Context, req *mgmt_pb.Re
|
||||
}
|
||||
|
||||
func (s *Server) RegenerateAPIClientSecret(ctx context.Context, req *mgmt_pb.RegenerateAPIClientSecretRequest) (*mgmt_pb.RegenerateAPIClientSecretResponse, error) {
|
||||
config, err := s.command.ChangeAPIApplicationSecret(ctx, req.ProjectId, req.AppId, authz.GetCtxData(ctx).OrgID)
|
||||
appSecretGenerator, err := s.query.InitHashGenerator(ctx, domain.SecretGeneratorTypeAppSecret, s.PasswordHashAlg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config, err := s.command.ChangeAPIApplicationSecret(ctx, req.ProjectId, req.AppId, authz.GetCtxData(ctx).OrgID, appSecretGenerator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package management
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"google.golang.org/grpc"
|
||||
|
||||
"github.com/caos/zitadel/internal/api/authz"
|
||||
@ -19,18 +20,22 @@ var _ management.ManagementServiceServer = (*Server)(nil)
|
||||
|
||||
type Server struct {
|
||||
management.UnimplementedManagementServiceServer
|
||||
command *command.Commands
|
||||
query *query.Queries
|
||||
systemDefaults systemdefaults.SystemDefaults
|
||||
assetAPIPrefix string
|
||||
command *command.Commands
|
||||
query *query.Queries
|
||||
systemDefaults systemdefaults.SystemDefaults
|
||||
assetAPIPrefix string
|
||||
PasswordHashAlg crypto.HashAlgorithm
|
||||
UserCodeAlg crypto.EncryptionAlgorithm
|
||||
}
|
||||
|
||||
func CreateServer(command *command.Commands, query *query.Queries, sd systemdefaults.SystemDefaults, assetAPIPrefix string) *Server {
|
||||
func CreateServer(command *command.Commands, query *query.Queries, sd systemdefaults.SystemDefaults, assetAPIPrefix string, userCrypto *crypto.AESCrypto) *Server {
|
||||
return &Server{
|
||||
command: command,
|
||||
query: query,
|
||||
systemDefaults: sd,
|
||||
assetAPIPrefix: assetAPIPrefix,
|
||||
command: command,
|
||||
query: query,
|
||||
systemDefaults: sd,
|
||||
assetAPIPrefix: assetAPIPrefix,
|
||||
PasswordHashAlg: crypto.NewBCrypt(sd.SecretGenerators.PasswordSaltCost),
|
||||
UserCodeAlg: userCrypto,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -192,7 +192,15 @@ func (s *Server) BulkRemoveUserMetadata(ctx context.Context, req *mgmt_pb.BulkRe
|
||||
}
|
||||
|
||||
func (s *Server) AddHumanUser(ctx context.Context, req *mgmt_pb.AddHumanUserRequest) (*mgmt_pb.AddHumanUserResponse, error) {
|
||||
human, err := s.command.AddHuman(ctx, authz.GetCtxData(ctx).OrgID, AddHumanUserRequestToDomain(req))
|
||||
initCodeGenerator, err := s.query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypeInitCode, s.UserCodeAlg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
phoneCodeGenerator, err := s.query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypeVerifyPhoneCode, s.UserCodeAlg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
human, err := s.command.AddHuman(ctx, authz.GetCtxData(ctx).OrgID, AddHumanUserRequestToDomain(req), initCodeGenerator, phoneCodeGenerator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -208,7 +216,19 @@ func (s *Server) AddHumanUser(ctx context.Context, req *mgmt_pb.AddHumanUserRequ
|
||||
|
||||
func (s *Server) ImportHumanUser(ctx context.Context, req *mgmt_pb.ImportHumanUserRequest) (*mgmt_pb.ImportHumanUserResponse, error) {
|
||||
human, passwordless := ImportHumanUserRequestToDomain(req)
|
||||
addedHuman, code, err := s.command.ImportHuman(ctx, authz.GetCtxData(ctx).OrgID, human, passwordless)
|
||||
initCodeGenerator, err := s.query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypeInitCode, s.UserCodeAlg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
phoneCodeGenerator, err := s.query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypeVerifyPhoneCode, s.UserCodeAlg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
passwordlessInitCode, err := s.query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypePasswordlessInitCode, s.UserCodeAlg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
addedHuman, code, err := s.command.ImportHuman(ctx, authz.GetCtxData(ctx).OrgID, human, passwordless, initCodeGenerator, phoneCodeGenerator, passwordlessInitCode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -388,7 +408,11 @@ func (s *Server) GetHumanEmail(ctx context.Context, req *mgmt_pb.GetHumanEmailRe
|
||||
}
|
||||
|
||||
func (s *Server) UpdateHumanEmail(ctx context.Context, req *mgmt_pb.UpdateHumanEmailRequest) (*mgmt_pb.UpdateHumanEmailResponse, error) {
|
||||
email, err := s.command.ChangeHumanEmail(ctx, UpdateHumanEmailRequestToDomain(ctx, req))
|
||||
emailCodeGenerator, err := s.query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypeVerifyEmailCode, s.UserCodeAlg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
email, err := s.command.ChangeHumanEmail(ctx, UpdateHumanEmailRequestToDomain(ctx, req), emailCodeGenerator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -402,7 +426,11 @@ func (s *Server) UpdateHumanEmail(ctx context.Context, req *mgmt_pb.UpdateHumanE
|
||||
}
|
||||
|
||||
func (s *Server) ResendHumanInitialization(ctx context.Context, req *mgmt_pb.ResendHumanInitializationRequest) (*mgmt_pb.ResendHumanInitializationResponse, error) {
|
||||
details, err := s.command.ResendInitialMail(ctx, req.UserId, req.Email, authz.GetCtxData(ctx).OrgID)
|
||||
initCodeGenerator, err := s.query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypeInitCode, s.UserCodeAlg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
details, err := s.command.ResendInitialMail(ctx, req.UserId, req.Email, authz.GetCtxData(ctx).OrgID, initCodeGenerator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -412,7 +440,11 @@ func (s *Server) ResendHumanInitialization(ctx context.Context, req *mgmt_pb.Res
|
||||
}
|
||||
|
||||
func (s *Server) ResendHumanEmailVerification(ctx context.Context, req *mgmt_pb.ResendHumanEmailVerificationRequest) (*mgmt_pb.ResendHumanEmailVerificationResponse, error) {
|
||||
objectDetails, err := s.command.CreateHumanEmailVerificationCode(ctx, req.UserId, authz.GetCtxData(ctx).OrgID)
|
||||
emailCodeGenerator, err := s.query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypeVerifyEmailCode, s.UserCodeAlg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
objectDetails, err := s.command.CreateHumanEmailVerificationCode(ctx, req.UserId, authz.GetCtxData(ctx).OrgID, emailCodeGenerator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -442,7 +474,11 @@ func (s *Server) GetHumanPhone(ctx context.Context, req *mgmt_pb.GetHumanPhoneRe
|
||||
}
|
||||
|
||||
func (s *Server) UpdateHumanPhone(ctx context.Context, req *mgmt_pb.UpdateHumanPhoneRequest) (*mgmt_pb.UpdateHumanPhoneResponse, error) {
|
||||
phone, err := s.command.ChangeHumanPhone(ctx, UpdateHumanPhoneRequestToDomain(req), authz.GetCtxData(ctx).OrgID)
|
||||
phoneCodeGenerator, err := s.query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypeVerifyPhoneCode, s.UserCodeAlg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
phone, err := s.command.ChangeHumanPhone(ctx, UpdateHumanPhoneRequestToDomain(req), authz.GetCtxData(ctx).OrgID, phoneCodeGenerator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -466,7 +502,11 @@ func (s *Server) RemoveHumanPhone(ctx context.Context, req *mgmt_pb.RemoveHumanP
|
||||
}
|
||||
|
||||
func (s *Server) ResendHumanPhoneVerification(ctx context.Context, req *mgmt_pb.ResendHumanPhoneVerificationRequest) (*mgmt_pb.ResendHumanPhoneVerificationResponse, error) {
|
||||
objectDetails, err := s.command.CreateHumanPhoneVerificationCode(ctx, req.UserId, authz.GetCtxData(ctx).OrgID)
|
||||
phoneCodeGenerator, err := s.query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypeVerifyPhoneCode, s.UserCodeAlg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
objectDetails, err := s.command.CreateHumanPhoneVerificationCode(ctx, req.UserId, authz.GetCtxData(ctx).OrgID, phoneCodeGenerator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -507,7 +547,11 @@ func (s *Server) SetHumanPassword(ctx context.Context, req *mgmt_pb.SetHumanPass
|
||||
}
|
||||
|
||||
func (s *Server) SendHumanResetPasswordNotification(ctx context.Context, req *mgmt_pb.SendHumanResetPasswordNotificationRequest) (*mgmt_pb.SendHumanResetPasswordNotificationResponse, error) {
|
||||
objectDetails, err := s.command.RequestSetPassword(ctx, req.UserId, authz.GetCtxData(ctx).OrgID, notifyTypeToDomain(req.Type))
|
||||
passwordCodeGenerator, err := s.query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypePasswordResetCode, s.UserCodeAlg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
objectDetails, err := s.command.RequestSetPassword(ctx, req.UserId, authz.GetCtxData(ctx).OrgID, notifyTypeToDomain(req.Type), passwordCodeGenerator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -584,7 +628,11 @@ func (s *Server) ListHumanPasswordless(ctx context.Context, req *mgmt_pb.ListHum
|
||||
|
||||
func (s *Server) AddPasswordlessRegistration(ctx context.Context, req *mgmt_pb.AddPasswordlessRegistrationRequest) (*mgmt_pb.AddPasswordlessRegistrationResponse, error) {
|
||||
ctxData := authz.GetCtxData(ctx)
|
||||
initCode, err := s.command.HumanAddPasswordlessInitCode(ctx, req.UserId, ctxData.OrgID)
|
||||
passwordlessInitCode, err := s.query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypePasswordlessInitCode, s.UserCodeAlg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
initCode, err := s.command.HumanAddPasswordlessInitCode(ctx, req.UserId, ctxData.OrgID, passwordlessInitCode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -597,7 +645,11 @@ func (s *Server) AddPasswordlessRegistration(ctx context.Context, req *mgmt_pb.A
|
||||
|
||||
func (s *Server) SendPasswordlessRegistration(ctx context.Context, req *mgmt_pb.SendPasswordlessRegistrationRequest) (*mgmt_pb.SendPasswordlessRegistrationResponse, error) {
|
||||
ctxData := authz.GetCtxData(ctx)
|
||||
initCode, err := s.command.HumanSendPasswordlessInitCode(ctx, req.UserId, ctxData.OrgID)
|
||||
passwordlessInitCode, err := s.query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypePasswordlessInitCode, s.UserCodeAlg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
initCode, err := s.command.HumanSendPasswordlessInitCode(ctx, req.UserId, ctxData.OrgID, passwordlessInitCode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -3,15 +3,14 @@ package middleware
|
||||
import (
|
||||
"context"
|
||||
|
||||
"golang.org/x/text/language"
|
||||
|
||||
"github.com/caos/zitadel/internal/query"
|
||||
"google.golang.org/grpc"
|
||||
|
||||
_ "github.com/caos/zitadel/internal/statik"
|
||||
)
|
||||
|
||||
func TranslationHandler(defaultLanguage language.Tag) func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
||||
translator := newZitadelTranslator(defaultLanguage)
|
||||
func TranslationHandler(query *query.Queries) func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
||||
translator := newZitadelTranslator(query.GetDefaultLanguage(context.Background()))
|
||||
|
||||
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
||||
resp, err := handler(ctx, req)
|
||||
|
@ -2,10 +2,10 @@ package server
|
||||
|
||||
import (
|
||||
grpc_api "github.com/caos/zitadel/internal/api/grpc"
|
||||
"github.com/caos/zitadel/internal/query"
|
||||
"github.com/caos/zitadel/internal/telemetry/metrics"
|
||||
|
||||
grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
|
||||
"golang.org/x/text/language"
|
||||
"google.golang.org/grpc"
|
||||
|
||||
"github.com/caos/zitadel/internal/api/authz"
|
||||
@ -20,7 +20,7 @@ type Server interface {
|
||||
AuthMethods() authz.MethodMapping
|
||||
}
|
||||
|
||||
func CreateServer(verifier *authz.TokenVerifier, authConfig authz.Config, lang language.Tag) *grpc.Server {
|
||||
func CreateServer(verifier *authz.TokenVerifier, authConfig authz.Config, queries *query.Queries) *grpc.Server {
|
||||
metricTypes := []metrics.MetricType{metrics.MetricTypeTotalCount, metrics.MetricTypeRequestCount, metrics.MetricTypeStatusCode}
|
||||
return grpc.NewServer(
|
||||
grpc.UnaryInterceptor(
|
||||
@ -31,7 +31,7 @@ func CreateServer(verifier *authz.TokenVerifier, authConfig authz.Config, lang l
|
||||
middleware.NoCacheInterceptor(),
|
||||
middleware.ErrorHandler(),
|
||||
middleware.AuthorizationInterceptor(verifier, authConfig),
|
||||
middleware.TranslationHandler(lang),
|
||||
middleware.TranslationHandler(queries),
|
||||
middleware.ValidationHandler(),
|
||||
middleware.ServiceHandler(),
|
||||
),
|
||||
|
@ -145,7 +145,17 @@ func (l *Login) registerExternalUser(w http.ResponseWriter, r *http.Request, aut
|
||||
memberRoles = nil
|
||||
resourceOwner = authReq.RequestedOrgID
|
||||
}
|
||||
_, err := l.command.RegisterHuman(setContext(r.Context(), resourceOwner), resourceOwner, user, externalIDP, memberRoles)
|
||||
initCodeGenerator, err := l.query.InitEncryptionGenerator(r.Context(), domain.SecretGeneratorTypeInitCode, l.UserCodeAlg)
|
||||
if err != nil {
|
||||
l.renderRegisterOption(w, r, authReq, err)
|
||||
return
|
||||
}
|
||||
phoneCodeGenerator, err := l.query.InitEncryptionGenerator(r.Context(), domain.SecretGeneratorTypeVerifyPhoneCode, l.UserCodeAlg)
|
||||
if err != nil {
|
||||
l.renderRegisterOption(w, r, authReq, err)
|
||||
return
|
||||
}
|
||||
_, err = l.command.RegisterHuman(setContext(r.Context(), resourceOwner), resourceOwner, user, externalIDP, memberRoles, initCodeGenerator, phoneCodeGenerator)
|
||||
if err != nil {
|
||||
l.renderRegisterOption(w, r, authReq, err)
|
||||
return
|
||||
@ -216,7 +226,17 @@ func (l *Login) handleExternalRegisterCheck(w http.ResponseWriter, r *http.Reque
|
||||
l.renderRegisterOption(w, r, authReq, err)
|
||||
return
|
||||
}
|
||||
_, err = l.command.RegisterHuman(setContext(r.Context(), resourceOwner), resourceOwner, user, externalIDP, memberRoles)
|
||||
initCodeGenerator, err := l.query.InitEncryptionGenerator(r.Context(), domain.SecretGeneratorTypeInitCode, l.UserCodeAlg)
|
||||
if err != nil {
|
||||
l.renderRegisterOption(w, r, authReq, err)
|
||||
return
|
||||
}
|
||||
phoneCodeGenerator, err := l.query.InitEncryptionGenerator(r.Context(), domain.SecretGeneratorTypeVerifyPhoneCode, l.UserCodeAlg)
|
||||
if err != nil {
|
||||
l.renderRegisterOption(w, r, authReq, err)
|
||||
return
|
||||
}
|
||||
_, err = l.command.RegisterHuman(setContext(r.Context(), resourceOwner), resourceOwner, user, externalIDP, memberRoles, initCodeGenerator, phoneCodeGenerator)
|
||||
if err != nil {
|
||||
l.renderRegisterOption(w, r, authReq, err)
|
||||
return
|
||||
|
@ -70,7 +70,12 @@ func (l *Login) checkPWCode(w http.ResponseWriter, r *http.Request, authReq *dom
|
||||
userOrg = authReq.UserOrgID
|
||||
}
|
||||
userAgentID, _ := http_mw.UserAgentIDFromCtx(r.Context())
|
||||
err = l.command.SetPasswordWithVerifyCode(setContext(r.Context(), userOrg), userOrg, data.UserID, data.Code, data.Password, userAgentID)
|
||||
passwordCodeGenerator, err := l.query.InitEncryptionGenerator(r.Context(), domain.SecretGeneratorTypePasswordResetCode, l.UserCodeAlg)
|
||||
if err != nil {
|
||||
l.renderInitPassword(w, r, authReq, data.UserID, "", err)
|
||||
return
|
||||
}
|
||||
err = l.command.SetPasswordWithVerifyCode(setContext(r.Context(), userOrg), userOrg, data.UserID, data.Code, data.Password, userAgentID, passwordCodeGenerator)
|
||||
if err != nil {
|
||||
l.renderInitPassword(w, r, authReq, data.UserID, "", err)
|
||||
return
|
||||
@ -92,12 +97,17 @@ func (l *Login) resendPasswordSet(w http.ResponseWriter, r *http.Request, authRe
|
||||
l.renderInitPassword(w, r, authReq, authReq.UserID, "", err)
|
||||
return
|
||||
}
|
||||
passwordCodeGenerator, err := l.query.InitEncryptionGenerator(r.Context(), domain.SecretGeneratorTypePasswordResetCode, l.UserCodeAlg)
|
||||
if err != nil {
|
||||
l.renderInitPassword(w, r, authReq, authReq.UserID, "", err)
|
||||
return
|
||||
}
|
||||
user, err := l.query.GetUser(setContext(r.Context(), userOrg), loginName)
|
||||
if err != nil {
|
||||
l.renderInitPassword(w, r, authReq, authReq.UserID, "", err)
|
||||
return
|
||||
}
|
||||
_, err = l.command.RequestSetPassword(setContext(r.Context(), userOrg), user.ID, user.ResourceOwner, domain.NotificationTypeEmail)
|
||||
_, err = l.command.RequestSetPassword(setContext(r.Context(), userOrg), user.ID, user.ResourceOwner, domain.NotificationTypeEmail, passwordCodeGenerator)
|
||||
l.renderInitPassword(w, r, authReq, authReq.UserID, "", err)
|
||||
}
|
||||
|
||||
|
@ -73,7 +73,12 @@ func (l *Login) checkUserInitCode(w http.ResponseWriter, r *http.Request, authRe
|
||||
if authReq != nil {
|
||||
userOrgID = authReq.UserOrgID
|
||||
}
|
||||
err = l.command.HumanVerifyInitCode(setContext(r.Context(), userOrgID), data.UserID, userOrgID, data.Code, data.Password)
|
||||
initCodeGenerator, err := l.query.InitEncryptionGenerator(r.Context(), domain.SecretGeneratorTypeInitCode, l.UserCodeAlg)
|
||||
if err != nil {
|
||||
l.renderInitUser(w, r, authReq, data.UserID, "", data.PasswordSet, err)
|
||||
return
|
||||
}
|
||||
err = l.command.HumanVerifyInitCode(setContext(r.Context(), userOrgID), data.UserID, userOrgID, data.Code, data.Password, initCodeGenerator)
|
||||
if err != nil {
|
||||
l.renderInitUser(w, r, authReq, data.UserID, "", data.PasswordSet, err)
|
||||
return
|
||||
@ -86,7 +91,12 @@ func (l *Login) resendUserInit(w http.ResponseWriter, r *http.Request, authReq *
|
||||
if authReq != nil {
|
||||
userOrgID = authReq.UserOrgID
|
||||
}
|
||||
_, err := l.command.ResendInitialMail(setContext(r.Context(), userOrgID), userID, "", userOrgID)
|
||||
initCodeGenerator, err := l.query.InitEncryptionGenerator(r.Context(), domain.SecretGeneratorTypeInitCode, l.UserCodeAlg)
|
||||
if err != nil {
|
||||
l.renderInitUser(w, r, authReq, userID, "", showPassword, err)
|
||||
return
|
||||
}
|
||||
_, err = l.command.ResendInitialMail(setContext(r.Context(), userOrgID), userID, "", userOrgID, initCodeGenerator)
|
||||
l.renderInitUser(w, r, authReq, userID, "", showPassword, err)
|
||||
}
|
||||
|
||||
|
@ -38,6 +38,7 @@ type Login struct {
|
||||
zitadelURL string
|
||||
oidcAuthCallbackURL string
|
||||
IDPConfigAesCrypto crypto.EncryptionAlgorithm
|
||||
UserCodeAlg crypto.EncryptionAlgorithm
|
||||
iamDomain string
|
||||
}
|
||||
|
||||
@ -59,7 +60,7 @@ const (
|
||||
DefaultLoggedOutPath = HandlerPrefix + EndpointLogoutDone
|
||||
)
|
||||
|
||||
func CreateLogin(config Config, command *command.Commands, query *query.Queries, authRepo *eventsourcing.EsRepository, staticStorage static.Storage, systemDefaults systemdefaults.SystemDefaults, zitadelURL, domain, oidcAuthCallbackURL string, externalSecure bool, userAgentCookie mux.MiddlewareFunc) (*Login, error) {
|
||||
func CreateLogin(config Config, command *command.Commands, query *query.Queries, authRepo *eventsourcing.EsRepository, staticStorage static.Storage, systemDefaults systemdefaults.SystemDefaults, zitadelURL, domain, oidcAuthCallbackURL string, externalSecure bool, userAgentCookie mux.MiddlewareFunc, userCrypto *crypto.AESCrypto) (*Login, error) {
|
||||
aesCrypto, err := crypto.NewAESCrypto(systemDefaults.IDPConfigVerificationKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error create new aes crypto: %w", err)
|
||||
@ -74,6 +75,7 @@ func CreateLogin(config Config, command *command.Commands, query *query.Queries,
|
||||
authRepo: authRepo,
|
||||
IDPConfigAesCrypto: aesCrypto,
|
||||
iamDomain: domain,
|
||||
UserCodeAlg: userCrypto,
|
||||
}
|
||||
//TODO: enable when storage is implemented again
|
||||
//login.staticCache, err = config.StaticCache.Config.NewCache()
|
||||
|
@ -51,7 +51,12 @@ func (l *Login) handleMailVerificationCheck(w http.ResponseWriter, r *http.Reque
|
||||
if authReq != nil {
|
||||
userOrg = authReq.UserOrgID
|
||||
}
|
||||
_, err = l.command.CreateHumanEmailVerificationCode(setContext(r.Context(), userOrg), data.UserID, userOrg)
|
||||
emailCodeGenerator, err := l.query.InitEncryptionGenerator(r.Context(), domain.SecretGeneratorTypeVerifyEmailCode, l.UserCodeAlg)
|
||||
if err != nil {
|
||||
l.checkMailCode(w, r, authReq, data.UserID, data.Code)
|
||||
return
|
||||
}
|
||||
_, err = l.command.CreateHumanEmailVerificationCode(setContext(r.Context(), userOrg), data.UserID, userOrg, emailCodeGenerator)
|
||||
l.renderMailVerification(w, r, authReq, data.UserID, err)
|
||||
}
|
||||
|
||||
@ -61,7 +66,12 @@ func (l *Login) checkMailCode(w http.ResponseWriter, r *http.Request, authReq *d
|
||||
userID = authReq.UserID
|
||||
userOrg = authReq.UserOrgID
|
||||
}
|
||||
_, err := l.command.VerifyHumanEmail(setContext(r.Context(), userOrg), userID, code, userOrg)
|
||||
emailCodeGenerator, err := l.query.InitEncryptionGenerator(r.Context(), domain.SecretGeneratorTypeVerifyEmailCode, l.UserCodeAlg)
|
||||
if err != nil {
|
||||
l.renderMailVerification(w, r, authReq, userID, err)
|
||||
return
|
||||
}
|
||||
_, err = l.command.VerifyHumanEmail(setContext(r.Context(), userOrg), userID, code, userOrg, emailCodeGenerator)
|
||||
if err != nil {
|
||||
l.renderMailVerification(w, r, authReq, userID, err)
|
||||
return
|
||||
|
@ -27,7 +27,12 @@ func (l *Login) handlePasswordReset(w http.ResponseWriter, r *http.Request) {
|
||||
l.renderPasswordResetDone(w, r, authReq, err)
|
||||
return
|
||||
}
|
||||
_, err = l.command.RequestSetPassword(setContext(r.Context(), authReq.UserOrgID), user.ID, authReq.UserOrgID, domain.NotificationTypeEmail)
|
||||
passwordCodeGenerator, err := l.query.InitEncryptionGenerator(r.Context(), domain.SecretGeneratorTypePasswordResetCode, l.UserCodeAlg)
|
||||
if err != nil {
|
||||
l.renderPasswordResetDone(w, r, authReq, err)
|
||||
return
|
||||
}
|
||||
_, err = l.command.RequestSetPassword(setContext(r.Context(), authReq.UserOrgID), user.ID, authReq.UserOrgID, domain.NotificationTypeEmail, passwordCodeGenerator)
|
||||
l.renderPasswordResetDone(w, r, authReq, err)
|
||||
}
|
||||
|
||||
|
@ -74,7 +74,17 @@ func (l *Login) handleRegisterCheck(w http.ResponseWriter, r *http.Request) {
|
||||
memberRoles = nil
|
||||
resourceOwner = authRequest.RequestedOrgID
|
||||
}
|
||||
user, err := l.command.RegisterHuman(setContext(r.Context(), resourceOwner), resourceOwner, data.toHumanDomain(), nil, memberRoles)
|
||||
initCodeGenerator, err := l.query.InitEncryptionGenerator(r.Context(), domain.SecretGeneratorTypeInitCode, l.UserCodeAlg)
|
||||
if err != nil {
|
||||
l.renderRegister(w, r, authRequest, data, err)
|
||||
return
|
||||
}
|
||||
phoneCodeGenerator, err := l.query.InitEncryptionGenerator(r.Context(), domain.SecretGeneratorTypeVerifyPhoneCode, l.UserCodeAlg)
|
||||
if err != nil {
|
||||
l.renderRegister(w, r, authRequest, data, err)
|
||||
return
|
||||
}
|
||||
user, err := l.command.RegisterHuman(setContext(r.Context(), resourceOwner), resourceOwner, data.toHumanDomain(), nil, memberRoles, initCodeGenerator, phoneCodeGenerator)
|
||||
if err != nil {
|
||||
l.renderRegister(w, r, authRequest, data, err)
|
||||
return
|
||||
|
@ -65,7 +65,17 @@ func (l *Login) handleRegisterOrgCheck(w http.ResponseWriter, r *http.Request) {
|
||||
l.renderRegisterOrg(w, r, authRequest, data, err)
|
||||
return
|
||||
}
|
||||
_, err = l.command.SetUpOrg(ctx, data.toOrgDomain(), data.toUserDomain(), userIDs, true)
|
||||
initCodeGenerator, err := l.query.InitEncryptionGenerator(r.Context(), domain.SecretGeneratorTypePasswordlessInitCode, l.UserCodeAlg)
|
||||
if err != nil {
|
||||
l.renderRegisterOrg(w, r, authRequest, data, err)
|
||||
return
|
||||
}
|
||||
phoneCodeGenerator, err := l.query.InitEncryptionGenerator(r.Context(), domain.SecretGeneratorTypeVerifyPhoneCode, l.UserCodeAlg)
|
||||
if err != nil {
|
||||
l.renderRegisterOrg(w, r, authRequest, data, err)
|
||||
return
|
||||
}
|
||||
_, err = l.command.SetUpOrg(ctx, data.toOrgDomain(), data.toUserDomain(), initCodeGenerator, phoneCodeGenerator, userIDs, true)
|
||||
if err != nil {
|
||||
l.renderRegisterOrg(w, r, authRequest, data, err)
|
||||
return
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/caos/logging"
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
|
||||
"github.com/caos/zitadel/internal/api/authz"
|
||||
"github.com/caos/zitadel/internal/auth/repository/eventsourcing/view"
|
||||
@ -32,6 +33,7 @@ type AuthRequestRepo struct {
|
||||
AuthRequests cache.AuthRequestCache
|
||||
View *view.View
|
||||
Eventstore v1.Eventstore
|
||||
UserCodeAlg crypto.EncryptionAlgorithm
|
||||
|
||||
LabelPolicyProvider labelPolicyProvider
|
||||
UserSessionViewProvider userSessionViewProvider
|
||||
@ -54,8 +56,6 @@ type AuthRequestRepo struct {
|
||||
MFAInitSkippedLifeTime time.Duration
|
||||
SecondFactorCheckLifeTime time.Duration
|
||||
MultiFactorCheckLifeTime time.Duration
|
||||
|
||||
IAMID string
|
||||
}
|
||||
|
||||
type labelPolicyProvider interface {
|
||||
@ -381,13 +381,21 @@ func (repo *AuthRequestRepo) VerifyPasswordlessSetup(ctx context.Context, userID
|
||||
func (repo *AuthRequestRepo) BeginPasswordlessInitCodeSetup(ctx context.Context, userID, resourceOwner, codeID, verificationCode string, preferredPlatformType domain.AuthenticatorAttachment) (login *domain.WebAuthNToken, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
return repo.Command.HumanAddPasswordlessSetupInitCode(ctx, userID, resourceOwner, codeID, verificationCode, preferredPlatformType)
|
||||
passwordlessInitCode, err := repo.Query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypePasswordlessInitCode, repo.UserCodeAlg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return repo.Command.HumanAddPasswordlessSetupInitCode(ctx, userID, resourceOwner, codeID, verificationCode, preferredPlatformType, passwordlessInitCode)
|
||||
}
|
||||
|
||||
func (repo *AuthRequestRepo) VerifyPasswordlessInitCodeSetup(ctx context.Context, userID, resourceOwner, userAgentID, tokenName, codeID, verificationCode string, credentialData []byte) (err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
_, err = repo.Command.HumanPasswordlessSetupInitCode(ctx, userID, resourceOwner, tokenName, userAgentID, codeID, verificationCode, credentialData)
|
||||
passwordlessInitCode, err := repo.Query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypePasswordlessInitCode, repo.UserCodeAlg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = repo.Command.HumanPasswordlessSetupInitCode(ctx, userID, resourceOwner, tokenName, userAgentID, codeID, verificationCode, credentialData, passwordlessInitCode)
|
||||
return err
|
||||
}
|
||||
|
||||
@ -447,7 +455,15 @@ func (repo *AuthRequestRepo) AutoRegisterExternalUser(ctx context.Context, regis
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
human, err := repo.Command.RegisterHuman(ctx, resourceOwner, registerUser, externalIDP, orgMemberRoles)
|
||||
initCodeGenerator, err := repo.Query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypeInitCode, repo.UserCodeAlg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
phoneCodeGenerator, err := repo.Query.InitEncryptionGenerator(ctx, domain.SecretGeneratorTypeVerifyPhoneCode, repo.UserCodeAlg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
human, err := repo.Command.RegisterHuman(ctx, resourceOwner, registerUser, externalIDP, orgMemberRoles, initCodeGenerator, phoneCodeGenerator)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -519,7 +535,7 @@ func (repo *AuthRequestRepo) getLoginPolicyAndIDPProviders(ctx context.Context,
|
||||
if !policy.AllowExternalIDPs {
|
||||
return policy, nil, nil
|
||||
}
|
||||
idpProviders, err := getLoginPolicyIDPProviders(repo.IDPProviderViewProvider, repo.IAMID, orgID, policy.IsDefault)
|
||||
idpProviders, err := getLoginPolicyIDPProviders(repo.IDPProviderViewProvider, domain.IAMID, orgID, policy.IsDefault)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@ -534,7 +550,7 @@ func (repo *AuthRequestRepo) fillPolicies(ctx context.Context, request *domain.A
|
||||
orgID = request.UserOrgID
|
||||
}
|
||||
if orgID == "" {
|
||||
orgID = repo.IAMID
|
||||
orgID = domain.IAMID
|
||||
}
|
||||
|
||||
loginPolicy, idpProviders, err := repo.getLoginPolicyAndIDPProviders(ctx, orgID)
|
||||
|
@ -53,5 +53,5 @@ func (repo *OrgRepository) GetLoginText(ctx context.Context, orgID string) ([]*d
|
||||
}
|
||||
|
||||
func (p *OrgRepository) getIAMEvents(ctx context.Context, sequence uint64) ([]*models.Event, error) {
|
||||
return p.Eventstore.FilterEvents(ctx, models.NewSearchQuery().AggregateIDFilter(p.SystemDefaults.IamID).AggregateTypeFilter(iam.AggregateType))
|
||||
return p.Eventstore.FilterEvents(ctx, models.NewSearchQuery().AggregateIDFilter(domain.IAMID).AggregateTypeFilter(iam.AggregateType))
|
||||
}
|
||||
|
@ -32,8 +32,7 @@ func (h *handler) Eventstore() v1.Eventstore {
|
||||
func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es v1.Eventstore, systemDefaults sd.SystemDefaults, queries *query2.Queries) []query.Handler {
|
||||
return []query.Handler{
|
||||
newUser(
|
||||
handler{view, bulkLimit, configs.cycleDuration("User"), errorCount, es},
|
||||
systemDefaults.IamID, queries),
|
||||
handler{view, bulkLimit, configs.cycleDuration("User"), errorCount, es}, queries),
|
||||
newUserSession(
|
||||
handler{view, bulkLimit, configs.cycleDuration("UserSession"), errorCount, es}),
|
||||
newToken(
|
||||
|
@ -111,7 +111,7 @@ func (i *IDPProvider) processIdpProvider(event *es_models.Event) (err error) {
|
||||
case model.IDPConfigChanged, org_es_model.IDPConfigChanged:
|
||||
esConfig := new(iam_view_model.IDPConfigView)
|
||||
providerType := iam_model.IDPProviderTypeSystem
|
||||
if event.AggregateID != i.systemDefaults.IamID {
|
||||
if event.AggregateID != domain.IAMID {
|
||||
providerType = iam_model.IDPProviderTypeOrg
|
||||
}
|
||||
esConfig.AppendEvent(providerType, event)
|
||||
@ -120,7 +120,7 @@ func (i *IDPProvider) processIdpProvider(event *es_models.Event) (err error) {
|
||||
return err
|
||||
}
|
||||
config := new(query2.IDP)
|
||||
if event.AggregateID == i.systemDefaults.IamID {
|
||||
if event.AggregateID == domain.IAMID {
|
||||
config, err = i.getDefaultIDPConfig(context.TODO(), esConfig.IDPConfigID)
|
||||
} else {
|
||||
config, err = i.getOrgIDPConfig(context.TODO(), event.AggregateID, esConfig.IDPConfigID)
|
||||
|
@ -25,19 +25,16 @@ const (
|
||||
|
||||
type User struct {
|
||||
handler
|
||||
iamID string
|
||||
subscription *v1.Subscription
|
||||
queries *query2.Queries
|
||||
}
|
||||
|
||||
func newUser(
|
||||
handler handler,
|
||||
iamID string,
|
||||
queries *query2.Queries,
|
||||
) *User {
|
||||
h := &User{
|
||||
handler: handler,
|
||||
iamID: iamID,
|
||||
queries: queries,
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@ type EsRepository struct {
|
||||
eventstore.OrgRepository
|
||||
}
|
||||
|
||||
func Start(conf Config, systemDefaults sd.SystemDefaults, command *command.Commands, queries *query.Queries, dbClient *sql.DB, keyConfig *crypto.KeyConfig, assetsPrefix string) (*EsRepository, error) {
|
||||
func Start(conf Config, systemDefaults sd.SystemDefaults, command *command.Commands, queries *query.Queries, dbClient *sql.DB, keyConfig *crypto.KeyConfig, assetsPrefix string, userCrypto *crypto.AESCrypto) (*EsRepository, error) {
|
||||
es, err := v1.Start(dbClient)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -80,6 +80,7 @@ func Start(conf Config, systemDefaults sd.SystemDefaults, command *command.Comma
|
||||
AuthRequests: authReq,
|
||||
View: view,
|
||||
Eventstore: es,
|
||||
UserCodeAlg: userCrypto,
|
||||
UserSessionViewProvider: view,
|
||||
UserViewProvider: view,
|
||||
UserCommandProvider: command,
|
||||
@ -96,7 +97,6 @@ func Start(conf Config, systemDefaults sd.SystemDefaults, command *command.Comma
|
||||
MFAInitSkippedLifeTime: systemDefaults.VerificationLifetimes.MFAInitSkip,
|
||||
SecondFactorCheckLifeTime: systemDefaults.VerificationLifetimes.SecondFactorCheck,
|
||||
MultiFactorCheckLifeTime: systemDefaults.VerificationLifetimes.MultiFactorCheck,
|
||||
IAMID: systemDefaults.IamID,
|
||||
},
|
||||
eventstore.TokenRepo{
|
||||
View: view,
|
||||
|
@ -31,8 +31,7 @@ func (h *handler) Eventstore() v1.Eventstore {
|
||||
func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es v1.Eventstore, systemDefaults sd.SystemDefaults) []query.Handler {
|
||||
return []query.Handler{
|
||||
newUserGrant(
|
||||
handler{view, bulkLimit, configs.cycleDuration("UserGrants"), errorCount, es},
|
||||
systemDefaults.IamID),
|
||||
handler{view, bulkLimit, configs.cycleDuration("UserGrants"), errorCount, es}),
|
||||
newUserMembership(
|
||||
handler{view, bulkLimit, configs.cycleDuration("UserMemberships"), errorCount, es}),
|
||||
}
|
||||
|
@ -29,18 +29,15 @@ const (
|
||||
|
||||
type UserGrant struct {
|
||||
handler
|
||||
iamID string
|
||||
iamProjectID string
|
||||
subscription *v1.Subscription
|
||||
}
|
||||
|
||||
func newUserGrant(
|
||||
handler handler,
|
||||
iamID string,
|
||||
) *UserGrant {
|
||||
h := &UserGrant{
|
||||
handler: handler,
|
||||
iamID: iamID,
|
||||
}
|
||||
|
||||
h.subscribe()
|
||||
@ -151,15 +148,15 @@ func (u *UserGrant) processIAMMember(event *es_models.Event, rolePrefix string,
|
||||
case iam_es_model.IAMMemberAdded, iam_es_model.IAMMemberChanged:
|
||||
member.SetData(event)
|
||||
|
||||
grant, err := u.view.UserGrantByIDs(u.iamID, u.iamProjectID, member.UserID)
|
||||
grant, err := u.view.UserGrantByIDs(domain.IAMID, u.iamProjectID, member.UserID)
|
||||
if err != nil && !errors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
if errors.IsNotFound(err) {
|
||||
grant = &view_model.UserGrantView{
|
||||
ID: u.iamProjectID + member.UserID,
|
||||
ResourceOwner: u.iamID,
|
||||
OrgName: u.iamID,
|
||||
ResourceOwner: domain.IAMID,
|
||||
OrgName: domain.IAMID,
|
||||
ProjectID: u.iamProjectID,
|
||||
UserID: member.UserID,
|
||||
RoleKeys: member.Roles,
|
||||
@ -182,7 +179,7 @@ func (u *UserGrant) processIAMMember(event *es_models.Event, rolePrefix string,
|
||||
case iam_es_model.IAMMemberRemoved,
|
||||
iam_es_model.IAMMemberCascadeRemoved:
|
||||
member.SetData(event)
|
||||
grant, err := u.view.UserGrantByIDs(u.iamID, u.iamProjectID, member.UserID)
|
||||
grant, err := u.view.UserGrantByIDs(domain.IAMID, u.iamProjectID, member.UserID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -20,7 +20,6 @@ import (
|
||||
usr_repo "github.com/caos/zitadel/internal/repository/user"
|
||||
usr_grant_repo "github.com/caos/zitadel/internal/repository/usergrant"
|
||||
"github.com/caos/zitadel/internal/static"
|
||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||
webauthn_helper "github.com/caos/zitadel/internal/webauthn"
|
||||
)
|
||||
|
||||
@ -32,17 +31,11 @@ type Commands struct {
|
||||
zitadelRoles []authz.RoleMapping
|
||||
|
||||
idpConfigSecretCrypto crypto.EncryptionAlgorithm
|
||||
smtpPasswordCrypto crypto.EncryptionAlgorithm
|
||||
|
||||
userPasswordAlg crypto.HashAlgorithm
|
||||
initializeUserCode crypto.Generator
|
||||
emailVerificationCode crypto.Generator
|
||||
phoneVerificationCode crypto.Generator
|
||||
passwordVerificationCode crypto.Generator
|
||||
passwordlessInitCode crypto.Generator
|
||||
machineKeyAlg crypto.EncryptionAlgorithm
|
||||
machineKeySize int
|
||||
applicationKeySize int
|
||||
applicationSecretGenerator crypto.Generator
|
||||
domainVerificationAlg crypto.EncryptionAlgorithm
|
||||
domainVerificationGenerator crypto.Generator
|
||||
domainVerificationValidator func(domain, token, verifier string, checkType http.CheckType) error
|
||||
@ -60,7 +53,16 @@ type orgFeatureChecker interface {
|
||||
CheckOrgFeatures(ctx context.Context, orgID string, requiredFeatures ...string) error
|
||||
}
|
||||
|
||||
func StartCommands(es *eventstore.Eventstore, defaults sd.SystemDefaults, authZConfig authz.Config, staticStore static.Storage, authZRepo authz_repo.Repository, keyConfig *crypto.KeyConfig, webAuthN webauthn_helper.Config) (repo *Commands, err error) {
|
||||
func StartCommands(
|
||||
es *eventstore.Eventstore,
|
||||
defaults sd.SystemDefaults,
|
||||
authZConfig authz.Config,
|
||||
staticStore static.Storage,
|
||||
authZRepo authz_repo.Repository,
|
||||
keyConfig *crypto.KeyConfig,
|
||||
smtpPasswordEncAlg crypto.EncryptionAlgorithm,
|
||||
webAuthN webauthn_helper.Config,
|
||||
) (repo *Commands, err error) {
|
||||
repo = &Commands{
|
||||
eventstore: es,
|
||||
static: staticStore,
|
||||
@ -70,6 +72,7 @@ func StartCommands(es *eventstore.Eventstore, defaults sd.SystemDefaults, authZC
|
||||
keySize: defaults.KeyConfig.Size,
|
||||
privateKeyLifetime: defaults.KeyConfig.PrivateKeyLifetime,
|
||||
publicKeyLifetime: defaults.KeyConfig.PublicKeyLifetime,
|
||||
smtpPasswordCrypto: smtpPasswordEncAlg,
|
||||
}
|
||||
iam_repo.RegisterEventMappers(repo.eventstore)
|
||||
org.RegisterEventMappers(repo.eventstore)
|
||||
@ -83,17 +86,8 @@ func StartCommands(es *eventstore.Eventstore, defaults sd.SystemDefaults, authZC
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
userEncryptionAlgorithm, err := crypto.NewAESCrypto(defaults.UserVerificationKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
repo.initializeUserCode = crypto.NewEncryptionGenerator(defaults.SecretGenerators.InitializeUserCode, userEncryptionAlgorithm)
|
||||
repo.emailVerificationCode = crypto.NewEncryptionGenerator(defaults.SecretGenerators.EmailVerificationCode, userEncryptionAlgorithm)
|
||||
repo.phoneVerificationCode = crypto.NewEncryptionGenerator(defaults.SecretGenerators.PhoneVerificationCode, userEncryptionAlgorithm)
|
||||
repo.passwordVerificationCode = crypto.NewEncryptionGenerator(defaults.SecretGenerators.PasswordVerificationCode, userEncryptionAlgorithm)
|
||||
repo.passwordlessInitCode = crypto.NewEncryptionGenerator(defaults.SecretGenerators.PasswordlessInitCode, userEncryptionAlgorithm)
|
||||
|
||||
repo.userPasswordAlg = crypto.NewBCrypt(defaults.SecretGenerators.PasswordSaltCost)
|
||||
repo.machineKeyAlg = userEncryptionAlgorithm
|
||||
repo.machineKeySize = int(defaults.SecretGenerators.MachineKeySize)
|
||||
repo.applicationKeySize = int(defaults.SecretGenerators.ApplicationKeySize)
|
||||
|
||||
@ -107,8 +101,6 @@ func StartCommands(es *eventstore.Eventstore, defaults sd.SystemDefaults, authZC
|
||||
Issuer: defaults.Multifactors.OTP.Issuer,
|
||||
},
|
||||
}
|
||||
passwordAlg := crypto.NewBCrypt(defaults.SecretGenerators.PasswordSaltCost)
|
||||
repo.applicationSecretGenerator = crypto.NewHashGenerator(defaults.SecretGenerators.ClientSecretGenerator, passwordAlg)
|
||||
|
||||
repo.domainVerificationAlg, err = crypto.NewAESCrypto(defaults.DomainVerification.VerificationKey)
|
||||
if err != nil {
|
||||
@ -132,19 +124,6 @@ func StartCommands(es *eventstore.Eventstore, defaults sd.SystemDefaults, authZC
|
||||
return repo, nil
|
||||
}
|
||||
|
||||
func (c *Commands) getIAMWriteModel(ctx context.Context) (_ *IAMWriteModel, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
||||
writeModel := NewIAMWriteModel()
|
||||
err = c.eventstore.FilterToQueryReducer(ctx, writeModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return writeModel, nil
|
||||
}
|
||||
|
||||
func AppendAndReduce(object interface {
|
||||
AppendEvents(...eventstore.Event)
|
||||
Reduce() error
|
||||
|
@ -7,6 +7,8 @@ import (
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore"
|
||||
"github.com/caos/zitadel/internal/repository/iam"
|
||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
//TODO: private as soon as setup uses query
|
||||
@ -40,3 +42,33 @@ func (c *Commands) setIAMProject(ctx context.Context, iamAgg *eventstore.Aggrega
|
||||
}
|
||||
return iam.NewIAMProjectSetEvent(ctx, iamAgg, projectID), nil
|
||||
}
|
||||
|
||||
func (c *Commands) SetDefaultLanguage(ctx context.Context, language language.Tag) (*domain.ObjectDetails, error) {
|
||||
iamWriteModel, err := c.getIAMWriteModel(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
iamAgg := IAMAggregateFromWriteModel(&iamWriteModel.WriteModel)
|
||||
pushedEvents, err := c.eventstore.Push(ctx, iam.NewDefaultLanguageSetEvent(ctx, iamAgg, language))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(iamWriteModel, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToObjectDetails(&iamWriteModel.WriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) getIAMWriteModel(ctx context.Context) (_ *IAMWriteModel, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
||||
writeModel := NewIAMWriteModel()
|
||||
err = c.eventstore.FilterToQueryReducer(ctx, writeModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return writeModel, nil
|
||||
}
|
||||
|
@ -15,9 +15,8 @@ import (
|
||||
|
||||
func (c *Commands) AddDefaultIDPConfig(ctx context.Context, config *domain.IDPConfig) (*domain.IDPConfig, error) {
|
||||
if config.OIDCConfig == nil && config.JWTConfig == nil {
|
||||
return nil, errors.ThrowInvalidArgument(nil, "IAM-eUpQU", "Errors.idp.config.notset")
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "IDP-s8nn3", "Errors.IDPConfig.Invalid")
|
||||
}
|
||||
|
||||
idpConfigID, err := c.idGenerator.Next()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"github.com/caos/zitadel/internal/eventstore"
|
||||
"github.com/caos/zitadel/internal/repository/iam"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
type IAMWriteModel struct {
|
||||
@ -12,8 +13,9 @@ type IAMWriteModel struct {
|
||||
SetUpStarted domain.Step
|
||||
SetUpDone domain.Step
|
||||
|
||||
GlobalOrgID string
|
||||
ProjectID string
|
||||
GlobalOrgID string
|
||||
ProjectID string
|
||||
DefaultLanguage language.Tag
|
||||
}
|
||||
|
||||
func NewIAMWriteModel() *IAMWriteModel {
|
||||
@ -32,6 +34,8 @@ func (wm *IAMWriteModel) Reduce() error {
|
||||
wm.ProjectID = e.ProjectID
|
||||
case *iam.GlobalOrgSetEvent:
|
||||
wm.GlobalOrgID = e.OrgID
|
||||
case *iam.DefaultLanguageSetEvent:
|
||||
wm.DefaultLanguage = e.Language
|
||||
case *iam.SetupStepEvent:
|
||||
if e.Done {
|
||||
wm.SetUpDone = e.Step
|
||||
@ -52,6 +56,7 @@ func (wm *IAMWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
EventTypes(
|
||||
iam.ProjectSetEventType,
|
||||
iam.GlobalOrgSetEventType,
|
||||
iam.DefaultLanguageSetEventType,
|
||||
iam.SetupStartedEventType,
|
||||
iam.SetupDoneEventType).
|
||||
Builder()
|
||||
|
140
internal/command/iam_secret_generator_model.go
Normal file
140
internal/command/iam_secret_generator_model.go
Normal file
@ -0,0 +1,140 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"github.com/caos/zitadel/internal/eventstore"
|
||||
"github.com/caos/zitadel/internal/repository/iam"
|
||||
)
|
||||
|
||||
type IAMSecretGeneratorConfigWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
GeneratorType domain.SecretGeneratorType
|
||||
Length uint
|
||||
Expiry time.Duration
|
||||
IncludeLowerLetters bool
|
||||
IncludeUpperLetters bool
|
||||
IncludeDigits bool
|
||||
IncludeSymbols bool
|
||||
State domain.SecretGeneratorState
|
||||
}
|
||||
|
||||
func NewIAMSecretGeneratorConfigWriteModel(GeneratorType domain.SecretGeneratorType) *IAMSecretGeneratorConfigWriteModel {
|
||||
return &IAMSecretGeneratorConfigWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: domain.IAMID,
|
||||
ResourceOwner: domain.IAMID,
|
||||
},
|
||||
GeneratorType: GeneratorType,
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMSecretGeneratorConfigWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *iam.SecretGeneratorAddedEvent:
|
||||
if wm.GeneratorType != e.GeneratorType {
|
||||
continue
|
||||
}
|
||||
wm.Length = e.Length
|
||||
wm.Expiry = e.Expiry
|
||||
wm.IncludeLowerLetters = e.IncludeLowerLetters
|
||||
wm.IncludeUpperLetters = e.IncludeUpperLetters
|
||||
wm.IncludeDigits = e.IncludeDigits
|
||||
wm.IncludeSymbols = e.IncludeDigits
|
||||
wm.State = domain.SecretGeneratorStateActive
|
||||
case *iam.SecretGeneratorChangedEvent:
|
||||
if wm.GeneratorType != e.GeneratorType {
|
||||
continue
|
||||
}
|
||||
if e.Length != nil {
|
||||
wm.Length = *e.Length
|
||||
}
|
||||
if e.Expiry != nil {
|
||||
wm.Expiry = *e.Expiry
|
||||
}
|
||||
if e.IncludeUpperLetters != nil {
|
||||
wm.IncludeUpperLetters = *e.IncludeUpperLetters
|
||||
}
|
||||
if e.IncludeLowerLetters != nil {
|
||||
wm.IncludeLowerLetters = *e.IncludeLowerLetters
|
||||
}
|
||||
if e.IncludeDigits != nil {
|
||||
wm.IncludeDigits = *e.IncludeDigits
|
||||
}
|
||||
if e.IncludeSymbols != nil {
|
||||
wm.IncludeSymbols = *e.IncludeSymbols
|
||||
}
|
||||
case *iam.SecretGeneratorRemovedEvent:
|
||||
if wm.GeneratorType != e.GeneratorType {
|
||||
continue
|
||||
}
|
||||
wm.State = domain.SecretGeneratorStateRemoved
|
||||
wm.Length = 0
|
||||
wm.Expiry = 0
|
||||
wm.IncludeLowerLetters = false
|
||||
wm.IncludeUpperLetters = false
|
||||
wm.IncludeDigits = false
|
||||
wm.IncludeSymbols = false
|
||||
}
|
||||
}
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *IAMSecretGeneratorConfigWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
AddQuery().
|
||||
AggregateTypes(iam.AggregateType).
|
||||
AggregateIDs(wm.AggregateID).
|
||||
EventTypes(
|
||||
iam.SecretGeneratorAddedEventType,
|
||||
iam.SecretGeneratorChangedEventType,
|
||||
iam.SecretGeneratorRemovedEventType).
|
||||
Builder()
|
||||
}
|
||||
|
||||
func (wm *IAMSecretGeneratorConfigWriteModel) NewChangedEvent(
|
||||
ctx context.Context,
|
||||
aggregate *eventstore.Aggregate,
|
||||
generatorType domain.SecretGeneratorType,
|
||||
length uint,
|
||||
expiry time.Duration,
|
||||
includeLowerLetters,
|
||||
includeUpperLetters,
|
||||
includeDigits,
|
||||
includeSymbols bool,
|
||||
) (*iam.SecretGeneratorChangedEvent, bool, error) {
|
||||
changes := make([]iam.SecretGeneratorChanges, 0)
|
||||
var err error
|
||||
|
||||
if wm.Length != length {
|
||||
changes = append(changes, iam.ChangeSecretGeneratorLength(length))
|
||||
}
|
||||
if wm.Expiry != expiry {
|
||||
changes = append(changes, iam.ChangeSecretGeneratorExpiry(expiry))
|
||||
}
|
||||
if wm.IncludeLowerLetters != includeLowerLetters {
|
||||
changes = append(changes, iam.ChangeSecretGeneratorIncludeLowerLetters(includeLowerLetters))
|
||||
}
|
||||
if wm.IncludeUpperLetters != includeUpperLetters {
|
||||
changes = append(changes, iam.ChangeSecretGeneratorIncludeUpperLetters(includeUpperLetters))
|
||||
}
|
||||
if wm.IncludeDigits != includeDigits {
|
||||
changes = append(changes, iam.ChangeSecretGeneratorIncludeDigits(includeDigits))
|
||||
}
|
||||
if wm.IncludeSymbols != includeSymbols {
|
||||
changes = append(changes, iam.ChangeSecretGeneratorIncludeSymbols(includeSymbols))
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, false, nil
|
||||
}
|
||||
changeEvent, err := iam.NewSecretGeneratorChangeEvent(ctx, aggregate, generatorType, changes)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
return changeEvent, true, nil
|
||||
}
|
118
internal/command/iam_settings.go
Normal file
118
internal/command/iam_settings.go
Normal file
@ -0,0 +1,118 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/repository/iam"
|
||||
)
|
||||
|
||||
func (c *Commands) AddSecretGeneratorConfig(ctx context.Context, generatorType domain.SecretGeneratorType, config *crypto.GeneratorConfig) (*domain.ObjectDetails, error) {
|
||||
if generatorType == domain.SecretGeneratorTypeUnspecified {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-0pkwf", "Errors.SecretGenerator.TypeMissing")
|
||||
}
|
||||
|
||||
generatorWriteModel, err := c.getSecretConfig(ctx, generatorType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if generatorWriteModel.State == domain.SecretGeneratorStateActive {
|
||||
return nil, caos_errs.ThrowAlreadyExists(nil, "COMMAND-3n9ls", "Errors.SecretGenerator.AlreadyExists")
|
||||
}
|
||||
iamAgg := IAMAggregateFromWriteModel(&generatorWriteModel.WriteModel)
|
||||
pushedEvents, err := c.eventstore.Push(ctx, iam.NewSecretGeneratorAddedEvent(
|
||||
ctx,
|
||||
iamAgg,
|
||||
generatorType,
|
||||
config.Length,
|
||||
config.Expiry,
|
||||
config.IncludeLowerLetters,
|
||||
config.IncludeUpperLetters,
|
||||
config.IncludeDigits,
|
||||
config.IncludeSymbols))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(generatorWriteModel, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToObjectDetails(&generatorWriteModel.WriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) ChangeSecretGeneratorConfig(ctx context.Context, generatorType domain.SecretGeneratorType, config *crypto.GeneratorConfig) (*domain.ObjectDetails, error) {
|
||||
if generatorType == domain.SecretGeneratorTypeUnspecified {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-33k9f", "Errors.SecretGenerator.TypeMissing")
|
||||
}
|
||||
|
||||
generatorWriteModel, err := c.getSecretConfig(ctx, generatorType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if generatorWriteModel.State == domain.SecretGeneratorStateUnspecified || generatorWriteModel.State == domain.SecretGeneratorStateRemoved {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "COMMAND-3n9ls", "Errors.SecretGenerator.NotFound")
|
||||
}
|
||||
iamAgg := IAMAggregateFromWriteModel(&generatorWriteModel.WriteModel)
|
||||
|
||||
changedEvent, hasChanged, err := generatorWriteModel.NewChangedEvent(
|
||||
ctx,
|
||||
iamAgg,
|
||||
generatorType,
|
||||
config.Length,
|
||||
config.Expiry,
|
||||
config.IncludeLowerLetters,
|
||||
config.IncludeUpperLetters,
|
||||
config.IncludeDigits,
|
||||
config.IncludeSymbols)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-m0o3f", "Errors.NoChangesFound")
|
||||
}
|
||||
pushedEvents, err := c.eventstore.Push(ctx, changedEvent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(generatorWriteModel, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToObjectDetails(&generatorWriteModel.WriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) RemoveSecretGeneratorConfig(ctx context.Context, generatorType domain.SecretGeneratorType) (*domain.ObjectDetails, error) {
|
||||
if generatorType == domain.SecretGeneratorTypeUnspecified {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-2j9lw", "Errors.SecretGenerator.TypeMissing")
|
||||
}
|
||||
|
||||
generatorWriteModel, err := c.getSecretConfig(ctx, generatorType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if generatorWriteModel.State == domain.SecretGeneratorStateUnspecified || generatorWriteModel.State == domain.SecretGeneratorStateRemoved {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "COMMAND-b8les", "Errors.SecretGenerator.NotFound")
|
||||
}
|
||||
iamAgg := IAMAggregateFromWriteModel(&generatorWriteModel.WriteModel)
|
||||
pushedEvents, err := c.eventstore.Push(ctx, iam.NewSecretGeneratorRemovedEvent(ctx, iamAgg, generatorType))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(generatorWriteModel, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToObjectDetails(&generatorWriteModel.WriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) getSecretConfig(ctx context.Context, generatorType domain.SecretGeneratorType) (_ *IAMSecretGeneratorConfigWriteModel, err error) {
|
||||
writeModel := NewIAMSecretGeneratorConfigWriteModel(generatorType)
|
||||
err = c.eventstore.FilterToQueryReducer(ctx, writeModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return writeModel, nil
|
||||
}
|
512
internal/command/iam_settings_test.go
Normal file
512
internal/command/iam_settings_test.go
Normal file
@ -0,0 +1,512 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore"
|
||||
"github.com/caos/zitadel/internal/eventstore/repository"
|
||||
"github.com/caos/zitadel/internal/repository/iam"
|
||||
)
|
||||
|
||||
func TestCommandSide_AddSecretGenerator(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
generator *crypto.GeneratorConfig
|
||||
generatorType domain.SecretGeneratorType
|
||||
}
|
||||
type res struct {
|
||||
want *domain.ObjectDetails
|
||||
err func(error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "invalid empty type, error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
generator: &crypto.GeneratorConfig{},
|
||||
generatorType: domain.SecretGeneratorTypeUnspecified,
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "secret generator config, error already exists",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
iam.NewSecretGeneratorAddedEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
domain.SecretGeneratorTypeInitCode,
|
||||
4,
|
||||
time.Hour*1,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
generator: &crypto.GeneratorConfig{
|
||||
Length: 4,
|
||||
Expiry: 1 * time.Hour,
|
||||
IncludeLowerLetters: true,
|
||||
IncludeUpperLetters: true,
|
||||
IncludeDigits: true,
|
||||
IncludeSymbols: true,
|
||||
},
|
||||
generatorType: domain.SecretGeneratorTypeInitCode,
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsErrorAlreadyExists,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "add secret generator, ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(),
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
eventFromEventPusher(iam.NewSecretGeneratorAddedEvent(
|
||||
context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
domain.SecretGeneratorTypeInitCode,
|
||||
4,
|
||||
time.Hour*1,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
),
|
||||
),
|
||||
},
|
||||
uniqueConstraintsFromEventConstraint(iam.NewAddSecretGeneratorTypeUniqueConstraint(domain.SecretGeneratorTypeInitCode)),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
generator: &crypto.GeneratorConfig{
|
||||
Length: 4,
|
||||
Expiry: 1 * time.Hour,
|
||||
IncludeLowerLetters: true,
|
||||
IncludeUpperLetters: true,
|
||||
IncludeDigits: true,
|
||||
IncludeSymbols: true,
|
||||
},
|
||||
generatorType: domain.SecretGeneratorTypeInitCode,
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: "IAM",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
}
|
||||
got, err := r.AddSecretGeneratorConfig(tt.args.ctx, tt.args.generatorType, tt.args.generator)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
if tt.res.err != nil && !tt.res.err(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
if tt.res.err == nil {
|
||||
assert.Equal(t, tt.res.want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommandSide_ChangeSecretGenerator(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
generator *crypto.GeneratorConfig
|
||||
generatorType domain.SecretGeneratorType
|
||||
}
|
||||
type res struct {
|
||||
want *domain.ObjectDetails
|
||||
err func(error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "empty generatortype, invalid error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
generator: &crypto.GeneratorConfig{},
|
||||
generatorType: domain.SecretGeneratorTypeUnspecified,
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "generator not existing, not found error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
generatorType: domain.SecretGeneratorTypeInitCode,
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsNotFound,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "generator removed, not found error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
iam.NewSecretGeneratorAddedEvent(
|
||||
context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
domain.SecretGeneratorTypeInitCode,
|
||||
4,
|
||||
time.Hour*1,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
iam.NewSecretGeneratorRemovedEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
domain.SecretGeneratorTypeInitCode),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
generatorType: domain.SecretGeneratorTypeInitCode,
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsNotFound,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "no changes, precondition error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
iam.NewSecretGeneratorAddedEvent(
|
||||
context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
domain.SecretGeneratorTypeInitCode,
|
||||
4,
|
||||
time.Hour*1,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
generator: &crypto.GeneratorConfig{
|
||||
Length: 4,
|
||||
Expiry: 1 * time.Hour,
|
||||
IncludeLowerLetters: true,
|
||||
IncludeUpperLetters: true,
|
||||
IncludeDigits: true,
|
||||
IncludeSymbols: true,
|
||||
},
|
||||
generatorType: domain.SecretGeneratorTypeInitCode,
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "secret generator change, ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
iam.NewSecretGeneratorAddedEvent(
|
||||
context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
domain.SecretGeneratorTypeInitCode,
|
||||
4,
|
||||
time.Hour*1,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
eventFromEventPusher(
|
||||
newSecretGeneratorChangedEvent(context.Background(),
|
||||
domain.SecretGeneratorTypeInitCode,
|
||||
8,
|
||||
time.Hour*2,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false),
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
generator: &crypto.GeneratorConfig{
|
||||
Length: 8,
|
||||
Expiry: 2 * time.Hour,
|
||||
IncludeLowerLetters: false,
|
||||
IncludeUpperLetters: false,
|
||||
IncludeDigits: false,
|
||||
IncludeSymbols: false,
|
||||
},
|
||||
generatorType: domain.SecretGeneratorTypeInitCode,
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: "IAM",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
}
|
||||
got, err := r.ChangeSecretGeneratorConfig(tt.args.ctx, tt.args.generatorType, tt.args.generator)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
if tt.res.err != nil && !tt.res.err(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
if tt.res.err == nil {
|
||||
assert.Equal(t, tt.res.want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommandSide_RemoveSecretGenerator(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
generatorType domain.SecretGeneratorType
|
||||
}
|
||||
type res struct {
|
||||
want *domain.ObjectDetails
|
||||
err func(error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "empty type, invalid error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
generatorType: domain.SecretGeneratorTypeUnspecified,
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "generator not existing, not found error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
generatorType: domain.SecretGeneratorTypeInitCode,
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsNotFound,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "generator removed, not found error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
iam.NewSecretGeneratorAddedEvent(
|
||||
context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
domain.SecretGeneratorTypeInitCode,
|
||||
4,
|
||||
time.Hour*1,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
iam.NewSecretGeneratorRemovedEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
domain.SecretGeneratorTypeInitCode),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
generatorType: domain.SecretGeneratorTypeInitCode,
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsNotFound,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "generator config remove, ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
iam.NewSecretGeneratorAddedEvent(
|
||||
context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
domain.SecretGeneratorTypeInitCode,
|
||||
4,
|
||||
time.Hour*1,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
eventFromEventPusher(
|
||||
iam.NewSecretGeneratorRemovedEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
domain.SecretGeneratorTypeInitCode),
|
||||
),
|
||||
},
|
||||
uniqueConstraintsFromEventConstraint(iam.NewRemoveSecretGeneratorTypeUniqueConstraint(domain.SecretGeneratorTypeInitCode)),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
generatorType: domain.SecretGeneratorTypeInitCode,
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: "IAM",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
}
|
||||
got, err := r.RemoveSecretGeneratorConfig(tt.args.ctx, tt.args.generatorType)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
if tt.res.err != nil && !tt.res.err(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
if tt.res.err == nil {
|
||||
assert.Equal(t, tt.res.want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func newSecretGeneratorChangedEvent(ctx context.Context, generatorType domain.SecretGeneratorType, length uint, expiry time.Duration, lowerCase, upperCase, digits, symbols bool) *iam.SecretGeneratorChangedEvent {
|
||||
changes := []iam.SecretGeneratorChanges{
|
||||
iam.ChangeSecretGeneratorLength(length),
|
||||
iam.ChangeSecretGeneratorExpiry(expiry),
|
||||
iam.ChangeSecretGeneratorIncludeLowerLetters(lowerCase),
|
||||
iam.ChangeSecretGeneratorIncludeUpperLetters(upperCase),
|
||||
iam.ChangeSecretGeneratorIncludeDigits(digits),
|
||||
iam.ChangeSecretGeneratorIncludeSymbols(symbols),
|
||||
}
|
||||
event, _ := iam.NewSecretGeneratorChangeEvent(ctx,
|
||||
&iam.NewAggregate().Aggregate,
|
||||
generatorType,
|
||||
changes,
|
||||
)
|
||||
return event
|
||||
}
|
106
internal/command/iam_smtp_config_model.go
Normal file
106
internal/command/iam_smtp_config_model.go
Normal file
@ -0,0 +1,106 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"github.com/caos/zitadel/internal/eventstore"
|
||||
"github.com/caos/zitadel/internal/repository/iam"
|
||||
)
|
||||
|
||||
type IAMSMTPConfigWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
SenderAddress string
|
||||
SenderName string
|
||||
TLS bool
|
||||
Host string
|
||||
User string
|
||||
Password *crypto.CryptoValue
|
||||
State domain.SMTPConfigState
|
||||
}
|
||||
|
||||
func NewIAMSMTPConfigWriteModel() *IAMSMTPConfigWriteModel {
|
||||
return &IAMSMTPConfigWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: domain.IAMID,
|
||||
ResourceOwner: domain.IAMID,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *IAMSMTPConfigWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *iam.SMTPConfigAddedEvent:
|
||||
wm.TLS = e.TLS
|
||||
wm.SenderAddress = e.SenderAddress
|
||||
wm.SenderName = e.SenderName
|
||||
wm.Host = e.Host
|
||||
wm.User = e.User
|
||||
wm.Password = e.Password
|
||||
wm.State = domain.SMTPConfigStateActive
|
||||
case *iam.SMTPConfigChangedEvent:
|
||||
if e.TLS != nil {
|
||||
wm.TLS = *e.TLS
|
||||
}
|
||||
if e.FromAddress != nil {
|
||||
wm.SenderAddress = *e.FromAddress
|
||||
}
|
||||
if e.FromName != nil {
|
||||
wm.SenderName = *e.FromName
|
||||
}
|
||||
if e.Host != nil {
|
||||
wm.Host = *e.Host
|
||||
}
|
||||
if e.User != nil {
|
||||
wm.User = *e.User
|
||||
}
|
||||
}
|
||||
}
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *IAMSMTPConfigWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
AddQuery().
|
||||
AggregateTypes(iam.AggregateType).
|
||||
AggregateIDs(wm.AggregateID).
|
||||
EventTypes(
|
||||
iam.SMTPConfigAddedEventType,
|
||||
iam.SMTPConfigChangedEventType,
|
||||
iam.SMTPConfigPasswordChangedEventType).
|
||||
Builder()
|
||||
}
|
||||
|
||||
func (wm *IAMSMTPConfigWriteModel) NewChangedEvent(ctx context.Context, aggregate *eventstore.Aggregate, tls bool, fromAddress, fromName, smtpHost, smtpUser string) (*iam.SMTPConfigChangedEvent, bool, error) {
|
||||
changes := make([]iam.SMTPConfigChanges, 0)
|
||||
var err error
|
||||
|
||||
if wm.TLS != tls {
|
||||
changes = append(changes, iam.ChangeSMTPConfigTLS(tls))
|
||||
}
|
||||
if wm.SenderAddress != fromAddress {
|
||||
changes = append(changes, iam.ChangeSMTPConfigFromAddress(fromAddress))
|
||||
}
|
||||
if wm.SenderName != fromName {
|
||||
changes = append(changes, iam.ChangeSMTPConfigFromName(fromName))
|
||||
}
|
||||
if wm.Host != smtpHost {
|
||||
changes = append(changes, iam.ChangeSMTPConfigSMTPHost(smtpHost))
|
||||
}
|
||||
if wm.User != smtpUser {
|
||||
changes = append(changes, iam.ChangeSMTPConfigSMTPUser(smtpUser))
|
||||
}
|
||||
|
||||
if len(changes) == 0 {
|
||||
return nil, false, nil
|
||||
}
|
||||
changeEvent, err := iam.NewSMTPConfigChangeEvent(ctx, aggregate, changes)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
return changeEvent, true, nil
|
||||
}
|
@ -3,6 +3,7 @@ package command
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore"
|
||||
@ -31,7 +32,7 @@ func (c *Commands) checkOrgExists(ctx context.Context, orgID string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Commands) SetUpOrg(ctx context.Context, organisation *domain.Org, admin *domain.Human, claimedUserIDs []string, selfregistered bool) (*domain.ObjectDetails, error) {
|
||||
func (c *Commands) SetUpOrg(ctx context.Context, organisation *domain.Org, admin *domain.Human, initCodeGenerator crypto.Generator, phoneCodeGenerator crypto.Generator, claimedUserIDs []string, selfregistered bool) (*domain.ObjectDetails, error) {
|
||||
orgIAMPolicy, err := c.getDefaultOrgIAMPolicy(ctx)
|
||||
if err != nil {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(err, "COMMAND-33M9f", "Errors.IAM.OrgIAMPolicy.NotFound")
|
||||
@ -40,7 +41,7 @@ func (c *Commands) SetUpOrg(ctx context.Context, organisation *domain.Org, admin
|
||||
if err != nil {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(err, "COMMAND-M5Fsd", "Errors.IAM.PasswordComplexity.NotFound")
|
||||
}
|
||||
_, orgWriteModel, _, _, events, err := c.setUpOrg(ctx, organisation, admin, orgIAMPolicy, pwPolicy, claimedUserIDs, selfregistered)
|
||||
_, orgWriteModel, _, _, events, err := c.setUpOrg(ctx, organisation, admin, orgIAMPolicy, pwPolicy, initCodeGenerator, phoneCodeGenerator, claimedUserIDs, selfregistered)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -168,6 +169,8 @@ func (c *Commands) setUpOrg(
|
||||
admin *domain.Human,
|
||||
loginPolicy *domain.OrgIAMPolicy,
|
||||
pwPolicy *domain.PasswordComplexityPolicy,
|
||||
initCodeGenerator crypto.Generator,
|
||||
phoneCodeGenerator crypto.Generator,
|
||||
claimedUserIDs []string,
|
||||
selfregistered bool,
|
||||
) (orgAgg *eventstore.Aggregate, org *OrgWriteModel, human *HumanWriteModel, orgMember *OrgMemberWriteModel, events []eventstore.Command, err error) {
|
||||
@ -178,9 +181,9 @@ func (c *Commands) setUpOrg(
|
||||
|
||||
var userEvents []eventstore.Command
|
||||
if selfregistered {
|
||||
userEvents, human, err = c.registerHuman(ctx, orgAgg.ID, admin, nil, loginPolicy, pwPolicy)
|
||||
userEvents, human, err = c.registerHuman(ctx, orgAgg.ID, admin, nil, loginPolicy, pwPolicy, initCodeGenerator, phoneCodeGenerator)
|
||||
} else {
|
||||
userEvents, human, err = c.addHuman(ctx, orgAgg.ID, admin, loginPolicy, pwPolicy)
|
||||
userEvents, human, err = c.addHuman(ctx, orgAgg.ID, admin, loginPolicy, pwPolicy, initCodeGenerator, phoneCodeGenerator)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, nil, err
|
||||
|
@ -13,7 +13,7 @@ import (
|
||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||
)
|
||||
|
||||
func (c *Commands) AddAPIApplication(ctx context.Context, application *domain.APIApp, resourceOwner string) (_ *domain.APIApp, err error) {
|
||||
func (c *Commands) AddAPIApplication(ctx context.Context, application *domain.APIApp, resourceOwner string, appSecretGenerator crypto.Generator) (_ *domain.APIApp, err error) {
|
||||
if application == nil || application.AggregateID == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "PROJECT-5m9E", "Errors.Application.Invalid")
|
||||
}
|
||||
@ -23,7 +23,7 @@ func (c *Commands) AddAPIApplication(ctx context.Context, application *domain.AP
|
||||
}
|
||||
addedApplication := NewAPIApplicationWriteModel(application.AggregateID, resourceOwner)
|
||||
projectAgg := ProjectAggregateFromWriteModel(&addedApplication.WriteModel)
|
||||
events, stringPw, err := c.addAPIApplication(ctx, projectAgg, project, application, resourceOwner)
|
||||
events, stringPw, err := c.addAPIApplication(ctx, projectAgg, project, application, resourceOwner, appSecretGenerator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -41,7 +41,7 @@ func (c *Commands) AddAPIApplication(ctx context.Context, application *domain.AP
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *Commands) addAPIApplication(ctx context.Context, projectAgg *eventstore.Aggregate, proj *domain.Project, apiAppApp *domain.APIApp, resourceOwner string) (events []eventstore.Command, stringPW string, err error) {
|
||||
func (c *Commands) addAPIApplication(ctx context.Context, projectAgg *eventstore.Aggregate, proj *domain.Project, apiAppApp *domain.APIApp, resourceOwner string, appSecretGenerator crypto.Generator) (events []eventstore.Command, stringPW string, err error) {
|
||||
if !apiAppApp.IsValid() {
|
||||
return nil, "", caos_errs.ThrowInvalidArgument(nil, "PROJECT-Bff2g", "Errors.Application.Invalid")
|
||||
}
|
||||
@ -59,7 +59,7 @@ func (c *Commands) addAPIApplication(ctx context.Context, projectAgg *eventstore
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
stringPw, err = domain.SetNewClientSecretIfNeeded(apiAppApp, c.applicationSecretGenerator)
|
||||
stringPw, err = domain.SetNewClientSecretIfNeeded(apiAppApp, appSecretGenerator)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
@ -113,7 +113,7 @@ func (c *Commands) ChangeAPIApplication(ctx context.Context, apiApp *domain.APIA
|
||||
return apiWriteModelToAPIConfig(existingAPI), nil
|
||||
}
|
||||
|
||||
func (c *Commands) ChangeAPIApplicationSecret(ctx context.Context, projectID, appID, resourceOwner string) (*domain.APIApp, error) {
|
||||
func (c *Commands) ChangeAPIApplicationSecret(ctx context.Context, projectID, appID, resourceOwner string, appSecretGenerator crypto.Generator) (*domain.APIApp, error) {
|
||||
if projectID == "" || appID == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-99i83", "Errors.IDMissing")
|
||||
}
|
||||
@ -128,7 +128,7 @@ func (c *Commands) ChangeAPIApplicationSecret(ctx context.Context, projectID, ap
|
||||
if !existingAPI.IsAPI() {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-aeH4", "Errors.Project.App.IsNotAPI")
|
||||
}
|
||||
cryptoSecret, stringPW, err := domain.NewClientSecret(c.applicationSecretGenerator)
|
||||
cryptoSecret, stringPW, err := domain.NewClientSecret(appSecretGenerator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
@ -12,19 +14,18 @@ import (
|
||||
id_mock "github.com/caos/zitadel/internal/id/mock"
|
||||
"github.com/caos/zitadel/internal/repository/project"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCommandSide_AddAPIApplication(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
idGenerator id.Generator
|
||||
secretGenerator crypto.Generator
|
||||
eventstore *eventstore.Eventstore
|
||||
idGenerator id.Generator
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
apiApp *domain.APIApp
|
||||
resourceOwner string
|
||||
ctx context.Context
|
||||
apiApp *domain.APIApp
|
||||
resourceOwner string
|
||||
secretGenerator crypto.Generator
|
||||
}
|
||||
type res struct {
|
||||
want *domain.APIApp
|
||||
@ -144,8 +145,7 @@ func TestCommandSide_AddAPIApplication(t *testing.T) {
|
||||
uniqueConstraintsFromEventConstraint(project.NewAddApplicationUniqueConstraint("app", "project1")),
|
||||
),
|
||||
),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "app1", "client1"),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "app1", "client1"),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
@ -156,7 +156,8 @@ func TestCommandSide_AddAPIApplication(t *testing.T) {
|
||||
AppName: "app",
|
||||
AuthMethodType: domain.APIAuthMethodTypeBasic,
|
||||
},
|
||||
resourceOwner: "org1",
|
||||
resourceOwner: "org1",
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
res: res{
|
||||
want: &domain.APIApp{
|
||||
@ -238,11 +239,10 @@ func TestCommandSide_AddAPIApplication(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
idGenerator: tt.fields.idGenerator,
|
||||
applicationSecretGenerator: tt.fields.secretGenerator,
|
||||
eventstore: tt.fields.eventstore,
|
||||
idGenerator: tt.fields.idGenerator,
|
||||
}
|
||||
got, err := r.AddAPIApplication(tt.args.ctx, tt.args.apiApp, tt.args.resourceOwner)
|
||||
got, err := r.AddAPIApplication(tt.args.ctx, tt.args.apiApp, tt.args.resourceOwner, tt.args.secretGenerator)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
@ -472,14 +472,14 @@ func TestCommandSide_ChangeAPIApplication(t *testing.T) {
|
||||
|
||||
func TestCommandSide_ChangeAPIApplicationSecret(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
secretGenerator crypto.Generator
|
||||
eventstore *eventstore.Eventstore
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
appID string
|
||||
projectID string
|
||||
resourceOwner string
|
||||
ctx context.Context
|
||||
appID string
|
||||
projectID string
|
||||
resourceOwner string
|
||||
secretGenerator crypto.Generator
|
||||
}
|
||||
type res struct {
|
||||
want *domain.APIApp
|
||||
@ -585,13 +585,13 @@ func TestCommandSide_ChangeAPIApplicationSecret(t *testing.T) {
|
||||
},
|
||||
),
|
||||
),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
projectID: "project1",
|
||||
appID: "app1",
|
||||
resourceOwner: "org1",
|
||||
ctx: context.Background(),
|
||||
projectID: "project1",
|
||||
appID: "app1",
|
||||
resourceOwner: "org1",
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
res: res{
|
||||
want: &domain.APIApp{
|
||||
@ -612,10 +612,9 @@ func TestCommandSide_ChangeAPIApplicationSecret(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
applicationSecretGenerator: tt.fields.secretGenerator,
|
||||
eventstore: tt.fields.eventstore,
|
||||
}
|
||||
got, err := r.ChangeAPIApplicationSecret(tt.args.ctx, tt.args.projectID, tt.args.appID, tt.args.resourceOwner)
|
||||
got, err := r.ChangeAPIApplicationSecret(tt.args.ctx, tt.args.projectID, tt.args.appID, tt.args.resourceOwner, tt.args.secretGenerator)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
@ -11,15 +13,13 @@ import (
|
||||
id_mock "github.com/caos/zitadel/internal/id/mock"
|
||||
"github.com/caos/zitadel/internal/repository/project"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCommandSide_AddAPIApplicationKey(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
idGenerator id.Generator
|
||||
secretGenerator crypto.Generator
|
||||
keySize int
|
||||
eventstore *eventstore.Eventstore
|
||||
idGenerator id.Generator
|
||||
keySize int
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
@ -126,8 +126,7 @@ func TestCommandSide_AddAPIApplicationKey(t *testing.T) {
|
||||
),
|
||||
),
|
||||
),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "key1"),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "key1"),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
@ -173,9 +172,8 @@ func TestCommandSide_AddAPIApplicationKey(t *testing.T) {
|
||||
),
|
||||
),
|
||||
),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "key1"),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
keySize: 10,
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "key1"),
|
||||
keySize: 10,
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
@ -195,10 +193,9 @@ func TestCommandSide_AddAPIApplicationKey(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
idGenerator: tt.fields.idGenerator,
|
||||
applicationSecretGenerator: tt.fields.secretGenerator,
|
||||
applicationKeySize: tt.fields.keySize,
|
||||
eventstore: tt.fields.eventstore,
|
||||
idGenerator: tt.fields.idGenerator,
|
||||
applicationKeySize: tt.fields.keySize,
|
||||
}
|
||||
got, err := r.AddApplicationKey(tt.args.ctx, tt.args.key, tt.args.resourceOwner)
|
||||
if tt.res.err == nil {
|
||||
|
@ -13,7 +13,7 @@ import (
|
||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||
)
|
||||
|
||||
func (c *Commands) AddOIDCApplication(ctx context.Context, application *domain.OIDCApp, resourceOwner string) (_ *domain.OIDCApp, err error) {
|
||||
func (c *Commands) AddOIDCApplication(ctx context.Context, application *domain.OIDCApp, resourceOwner string, appSecretGenerator crypto.Generator) (_ *domain.OIDCApp, err error) {
|
||||
if application == nil || application.AggregateID == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "PROJECT-34Fm0", "Errors.Application.Invalid")
|
||||
}
|
||||
@ -23,7 +23,7 @@ func (c *Commands) AddOIDCApplication(ctx context.Context, application *domain.O
|
||||
}
|
||||
addedApplication := NewOIDCApplicationWriteModel(application.AggregateID, resourceOwner)
|
||||
projectAgg := ProjectAggregateFromWriteModel(&addedApplication.WriteModel)
|
||||
events, stringPw, err := c.addOIDCApplication(ctx, projectAgg, project, application, resourceOwner)
|
||||
events, stringPw, err := c.addOIDCApplication(ctx, projectAgg, project, application, resourceOwner, appSecretGenerator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -42,7 +42,7 @@ func (c *Commands) AddOIDCApplication(ctx context.Context, application *domain.O
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *Commands) addOIDCApplication(ctx context.Context, projectAgg *eventstore.Aggregate, proj *domain.Project, oidcApp *domain.OIDCApp, resourceOwner string) (events []eventstore.Command, stringPW string, err error) {
|
||||
func (c *Commands) addOIDCApplication(ctx context.Context, projectAgg *eventstore.Aggregate, proj *domain.Project, oidcApp *domain.OIDCApp, resourceOwner string, appSecretGenerator crypto.Generator) (events []eventstore.Command, stringPW string, err error) {
|
||||
if oidcApp.AppName == "" || !oidcApp.IsValid() {
|
||||
return nil, "", caos_errs.ThrowInvalidArgument(nil, "PROJECT-1n8df", "Errors.Application.Invalid")
|
||||
}
|
||||
@ -60,7 +60,7 @@ func (c *Commands) addOIDCApplication(ctx context.Context, projectAgg *eventstor
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
stringPw, err = domain.SetNewClientSecretIfNeeded(oidcApp, c.applicationSecretGenerator)
|
||||
stringPw, err = domain.SetNewClientSecretIfNeeded(oidcApp, appSecretGenerator)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
@ -142,7 +142,7 @@ func (c *Commands) ChangeOIDCApplication(ctx context.Context, oidc *domain.OIDCA
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *Commands) ChangeOIDCApplicationSecret(ctx context.Context, projectID, appID, resourceOwner string) (*domain.OIDCApp, error) {
|
||||
func (c *Commands) ChangeOIDCApplicationSecret(ctx context.Context, projectID, appID, resourceOwner string, appSecretGenerator crypto.Generator) (*domain.OIDCApp, error) {
|
||||
if projectID == "" || appID == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-99i83", "Errors.IDMissing")
|
||||
}
|
||||
@ -157,7 +157,7 @@ func (c *Commands) ChangeOIDCApplicationSecret(ctx context.Context, projectID, a
|
||||
if !existingOIDC.IsOIDC() {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-Ghrh3", "Errors.Project.App.IsNotOIDC")
|
||||
}
|
||||
cryptoSecret, stringPW, err := domain.NewClientSecret(c.applicationSecretGenerator)
|
||||
cryptoSecret, stringPW, err := domain.NewClientSecret(appSecretGenerator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -20,14 +20,14 @@ import (
|
||||
|
||||
func TestCommandSide_AddOIDCApplication(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
idGenerator id.Generator
|
||||
secretGenerator crypto.Generator
|
||||
eventstore *eventstore.Eventstore
|
||||
idGenerator id.Generator
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
oidcApp *domain.OIDCApp
|
||||
resourceOwner string
|
||||
ctx context.Context
|
||||
oidcApp *domain.OIDCApp
|
||||
resourceOwner string
|
||||
secretGenerator crypto.Generator
|
||||
}
|
||||
type res struct {
|
||||
want *domain.OIDCApp
|
||||
@ -160,8 +160,7 @@ func TestCommandSide_AddOIDCApplication(t *testing.T) {
|
||||
uniqueConstraintsFromEventConstraint(project.NewAddApplicationUniqueConstraint("app", "project1")),
|
||||
),
|
||||
),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "app1", "client1"),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "app1", "client1"),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
@ -185,7 +184,8 @@ func TestCommandSide_AddOIDCApplication(t *testing.T) {
|
||||
ClockSkew: time.Second * 1,
|
||||
AdditionalOrigins: []string{"https://sub.test.ch"},
|
||||
},
|
||||
resourceOwner: "org1",
|
||||
resourceOwner: "org1",
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
res: res{
|
||||
want: &domain.OIDCApp{
|
||||
@ -220,11 +220,10 @@ func TestCommandSide_AddOIDCApplication(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
idGenerator: tt.fields.idGenerator,
|
||||
applicationSecretGenerator: tt.fields.secretGenerator,
|
||||
eventstore: tt.fields.eventstore,
|
||||
idGenerator: tt.fields.idGenerator,
|
||||
}
|
||||
got, err := r.AddOIDCApplication(tt.args.ctx, tt.args.oidcApp, tt.args.resourceOwner)
|
||||
got, err := r.AddOIDCApplication(tt.args.ctx, tt.args.oidcApp, tt.args.resourceOwner, tt.args.secretGenerator)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
@ -549,14 +548,14 @@ func TestCommandSide_ChangeOIDCApplication(t *testing.T) {
|
||||
|
||||
func TestCommandSide_ChangeOIDCApplicationSecret(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
secretGenerator crypto.Generator
|
||||
eventstore *eventstore.Eventstore
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
appID string
|
||||
projectID string
|
||||
resourceOwner string
|
||||
ctx context.Context
|
||||
appID string
|
||||
projectID string
|
||||
resourceOwner string
|
||||
secretGenerator crypto.Generator
|
||||
}
|
||||
type res struct {
|
||||
want *domain.OIDCApp
|
||||
@ -675,13 +674,13 @@ func TestCommandSide_ChangeOIDCApplicationSecret(t *testing.T) {
|
||||
},
|
||||
),
|
||||
),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
projectID: "project1",
|
||||
appID: "app1",
|
||||
resourceOwner: "org1",
|
||||
ctx: context.Background(),
|
||||
projectID: "project1",
|
||||
appID: "app1",
|
||||
resourceOwner: "org1",
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
res: res{
|
||||
want: &domain.OIDCApp{
|
||||
@ -715,10 +714,9 @@ func TestCommandSide_ChangeOIDCApplicationSecret(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
applicationSecretGenerator: tt.fields.secretGenerator,
|
||||
eventstore: tt.fields.eventstore,
|
||||
}
|
||||
got, err := r.ChangeOIDCApplicationSecret(tt.args.ctx, tt.args.projectID, tt.args.appID, tt.args.resourceOwner)
|
||||
got, err := r.ChangeOIDCApplicationSecret(tt.args.ctx, tt.args.projectID, tt.args.appID, tt.args.resourceOwner, tt.args.secretGenerator)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package command
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/eventstore"
|
||||
|
||||
"github.com/caos/zitadel/internal/eventstore/v1/models"
|
||||
@ -134,7 +135,10 @@ func (c *Commands) SetupStep1(ctx context.Context, step1 *Step1) error {
|
||||
EmailAddress: organisation.Owner.Email,
|
||||
IsEmailVerified: true,
|
||||
},
|
||||
}, orgIAMPolicy, pwPolicy, nil, false)
|
||||
}, orgIAMPolicy, pwPolicy,
|
||||
nil, //TODO: Code Generator missing! Should be setuped in step1 create iam
|
||||
nil, //TODO: Code Generator missing! Should be setuped in step1 create iam
|
||||
nil, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -180,14 +184,16 @@ func (c *Commands) SetupStep1(ctx context.Context, step1 *Step1) error {
|
||||
}
|
||||
//create applications
|
||||
for _, app := range proj.OIDCApps {
|
||||
applicationEvents, err := setUpOIDCApplication(ctx, c, projectWriteModel, project, app, orgAgg.ID)
|
||||
//TODO: Add Secret Generator
|
||||
applicationEvents, err := setUpOIDCApplication(ctx, c, projectWriteModel, project, app, orgAgg.ID, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
events = append(events, applicationEvents...)
|
||||
}
|
||||
for _, app := range proj.APIs {
|
||||
applicationEvents, err := setUpAPI(ctx, c, projectWriteModel, project, app, orgAgg.ID)
|
||||
//TODO: Add Secret Generator
|
||||
applicationEvents, err := setUpAPI(ctx, c, projectWriteModel, project, app, orgAgg.ID, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -205,7 +211,7 @@ func (c *Commands) SetupStep1(ctx context.Context, step1 *Step1) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func setUpOIDCApplication(ctx context.Context, r *Commands, projectWriteModel *ProjectWriteModel, project *domain.Project, oidcApp OIDCApp, resourceOwner string) ([]eventstore.Command, error) {
|
||||
func setUpOIDCApplication(ctx context.Context, r *Commands, projectWriteModel *ProjectWriteModel, project *domain.Project, oidcApp OIDCApp, resourceOwner string, appSecretGenerator crypto.Generator) ([]eventstore.Command, error) {
|
||||
app := &domain.OIDCApp{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: projectWriteModel.AggregateID,
|
||||
@ -220,7 +226,7 @@ func setUpOIDCApplication(ctx context.Context, r *Commands, projectWriteModel *P
|
||||
}
|
||||
|
||||
projectAgg := ProjectAggregateFromWriteModel(&projectWriteModel.WriteModel)
|
||||
events, _, err := r.addOIDCApplication(ctx, projectAgg, project, app, resourceOwner)
|
||||
events, _, err := r.addOIDCApplication(ctx, projectAgg, project, app, resourceOwner, appSecretGenerator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -228,7 +234,7 @@ func setUpOIDCApplication(ctx context.Context, r *Commands, projectWriteModel *P
|
||||
return events, nil
|
||||
}
|
||||
|
||||
func setUpAPI(ctx context.Context, r *Commands, projectWriteModel *ProjectWriteModel, project *domain.Project, apiApp API, resourceOwner string) ([]eventstore.Command, error) {
|
||||
func setUpAPI(ctx context.Context, r *Commands, projectWriteModel *ProjectWriteModel, project *domain.Project, apiApp API, resourceOwner string, appSecretGenerator crypto.Generator) ([]eventstore.Command, error) {
|
||||
app := &domain.APIApp{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: projectWriteModel.AggregateID,
|
||||
@ -238,7 +244,7 @@ func setUpAPI(ctx context.Context, r *Commands, projectWriteModel *ProjectWriteM
|
||||
}
|
||||
|
||||
projectAgg := ProjectAggregateFromWriteModel(&projectWriteModel.WriteModel)
|
||||
events, _, err := r.addAPIApplication(ctx, projectAgg, project, app, resourceOwner)
|
||||
events, _, err := r.addAPIApplication(ctx, projectAgg, project, app, resourceOwner, appSecretGenerator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
119
internal/command/smtp.go
Normal file
119
internal/command/smtp.go
Normal file
@ -0,0 +1,119 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/notification/channels/smtp"
|
||||
"github.com/caos/zitadel/internal/repository/iam"
|
||||
)
|
||||
|
||||
func (c *Commands) AddSMTPConfig(ctx context.Context, config *smtp.EmailConfig) (*domain.ObjectDetails, error) {
|
||||
smtpConfigWriteModel, err := c.getSMTPConfig(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if smtpConfigWriteModel.State == domain.SMTPConfigStateActive {
|
||||
return nil, caos_errs.ThrowAlreadyExists(nil, "COMMAND-en9lw", "Errors.SMTPConfig.AlreadyExists")
|
||||
}
|
||||
var smtpPassword *crypto.CryptoValue
|
||||
if config.SMTP.Password != "" {
|
||||
smtpPassword, err = crypto.Encrypt([]byte(config.SMTP.Password), c.smtpPasswordCrypto)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
iamAgg := IAMAggregateFromWriteModel(&smtpConfigWriteModel.WriteModel)
|
||||
pushedEvents, err := c.eventstore.Push(ctx, iam.NewSMTPConfigAddedEvent(
|
||||
ctx,
|
||||
iamAgg,
|
||||
config.Tls,
|
||||
config.From,
|
||||
config.FromName,
|
||||
config.SMTP.Host,
|
||||
config.SMTP.User,
|
||||
smtpPassword))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(smtpConfigWriteModel, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToObjectDetails(&smtpConfigWriteModel.WriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) ChangeSMTPConfig(ctx context.Context, config *smtp.EmailConfig) (*domain.ObjectDetails, error) {
|
||||
smtpConfigWriteModel, err := c.getSMTPConfig(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if smtpConfigWriteModel.State == domain.SMTPConfigStateUnspecified {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "COMMAND-3n9ls", "Errors.SMTPConfig.NotFound")
|
||||
}
|
||||
iamAgg := IAMAggregateFromWriteModel(&smtpConfigWriteModel.WriteModel)
|
||||
|
||||
changedEvent, hasChanged, err := smtpConfigWriteModel.NewChangedEvent(
|
||||
ctx,
|
||||
iamAgg,
|
||||
config.Tls,
|
||||
config.From,
|
||||
config.FromName,
|
||||
config.SMTP.Host,
|
||||
config.SMTP.User)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-m0o3f", "Errors.NoChangesFound")
|
||||
}
|
||||
pushedEvents, err := c.eventstore.Push(ctx, changedEvent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(smtpConfigWriteModel, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToObjectDetails(&smtpConfigWriteModel.WriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) ChangeSMTPConfigPassword(ctx context.Context, password string) (*domain.ObjectDetails, error) {
|
||||
smtpConfigWriteModel, err := c.getSMTPConfig(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if smtpConfigWriteModel.State == domain.SMTPConfigStateUnspecified {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "COMMAND-3n9ls", "Errors.SMTPConfig.NotFound")
|
||||
}
|
||||
iamAgg := IAMAggregateFromWriteModel(&smtpConfigWriteModel.WriteModel)
|
||||
newPW, err := crypto.Encrypt([]byte(password), c.smtpPasswordCrypto)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pushedEvents, err := c.eventstore.Push(ctx, iam.NewSMTPConfigPasswordChangedEvent(
|
||||
ctx,
|
||||
iamAgg,
|
||||
newPW))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(smtpConfigWriteModel, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToObjectDetails(&smtpConfigWriteModel.WriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) getSMTPConfig(ctx context.Context) (_ *IAMSMTPConfigWriteModel, err error) {
|
||||
writeModel := NewIAMSMTPConfigWriteModel()
|
||||
err = c.eventstore.FilterToQueryReducer(ctx, writeModel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return writeModel, nil
|
||||
}
|
398
internal/command/smtp_test.go
Normal file
398
internal/command/smtp_test.go
Normal file
@ -0,0 +1,398 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/notification/channels/smtp"
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore"
|
||||
"github.com/caos/zitadel/internal/eventstore/repository"
|
||||
"github.com/caos/zitadel/internal/repository/iam"
|
||||
)
|
||||
|
||||
func TestCommandSide_AddSMTPConfig(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
alg crypto.EncryptionAlgorithm
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
smtp *smtp.EmailConfig
|
||||
}
|
||||
type res struct {
|
||||
want *domain.ObjectDetails
|
||||
err func(error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "smtp config, error already exists",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
iam.NewSMTPConfigAddedEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
true,
|
||||
"from",
|
||||
"name",
|
||||
"host",
|
||||
"user",
|
||||
&crypto.CryptoValue{},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
smtp: &smtp.EmailConfig{
|
||||
Tls: true,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsErrorAlreadyExists,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "add smtp config, ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(),
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
eventFromEventPusher(iam.NewSMTPConfigAddedEvent(
|
||||
context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
true,
|
||||
"from",
|
||||
"name",
|
||||
"host",
|
||||
"user",
|
||||
&crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
KeyID: "id",
|
||||
Crypted: []byte("password"),
|
||||
},
|
||||
),
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
alg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
smtp: &smtp.EmailConfig{
|
||||
Tls: true,
|
||||
From: "from",
|
||||
FromName: "name",
|
||||
SMTP: smtp.SMTP{
|
||||
Host: "host",
|
||||
User: "user",
|
||||
Password: "password",
|
||||
},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: "IAM",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
smtpPasswordCrypto: tt.fields.alg,
|
||||
}
|
||||
got, err := r.AddSMTPConfig(tt.args.ctx, tt.args.smtp)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
if tt.res.err != nil && !tt.res.err(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
if tt.res.err == nil {
|
||||
assert.Equal(t, tt.res.want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommandSide_ChangeSMTPConfig(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
smtp *smtp.EmailConfig
|
||||
}
|
||||
type res struct {
|
||||
want *domain.ObjectDetails
|
||||
err func(error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "smtp not existing, not found error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
smtp: &smtp.EmailConfig{},
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsNotFound,
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "no changes, precondition error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
iam.NewSMTPConfigAddedEvent(
|
||||
context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
true,
|
||||
"from",
|
||||
"name",
|
||||
"host",
|
||||
"user",
|
||||
&crypto.CryptoValue{},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
smtp: &smtp.EmailConfig{
|
||||
Tls: true,
|
||||
From: "from",
|
||||
FromName: "name",
|
||||
SMTP: smtp.SMTP{
|
||||
Host: "host",
|
||||
User: "user",
|
||||
},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "smtp config change, ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
iam.NewSMTPConfigAddedEvent(
|
||||
context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
true,
|
||||
"from",
|
||||
"name",
|
||||
"host",
|
||||
"user",
|
||||
&crypto.CryptoValue{},
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
eventFromEventPusher(
|
||||
newSMTPConfigChangedEvent(
|
||||
context.Background(),
|
||||
false,
|
||||
"from2",
|
||||
"name2",
|
||||
"host2",
|
||||
"user2",
|
||||
),
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
smtp: &smtp.EmailConfig{
|
||||
Tls: false,
|
||||
From: "from2",
|
||||
FromName: "name2",
|
||||
SMTP: smtp.SMTP{
|
||||
Host: "host2",
|
||||
User: "user2",
|
||||
},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: "IAM",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
}
|
||||
got, err := r.ChangeSMTPConfig(tt.args.ctx, tt.args.smtp)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
if tt.res.err != nil && !tt.res.err(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
if tt.res.err == nil {
|
||||
assert.Equal(t, tt.res.want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommandSide_ChangeSMTPConfigPassword(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
alg crypto.EncryptionAlgorithm
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
password string
|
||||
}
|
||||
type res struct {
|
||||
want *domain.ObjectDetails
|
||||
err func(error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "smtp config, error not found",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
password: "",
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsNotFound,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "change smtp config password, ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
iam.NewSMTPConfigAddedEvent(
|
||||
context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
true,
|
||||
"from",
|
||||
"name",
|
||||
"host",
|
||||
"user",
|
||||
&crypto.CryptoValue{},
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
[]*repository.Event{
|
||||
eventFromEventPusher(iam.NewSMTPConfigPasswordChangedEvent(
|
||||
context.Background(),
|
||||
&iam.NewAggregate().Aggregate,
|
||||
&crypto.CryptoValue{
|
||||
CryptoType: crypto.TypeEncryption,
|
||||
Algorithm: "enc",
|
||||
KeyID: "id",
|
||||
Crypted: []byte("password"),
|
||||
},
|
||||
),
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
alg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
password: "password",
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: "IAM",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
smtpPasswordCrypto: tt.fields.alg,
|
||||
}
|
||||
got, err := r.ChangeSMTPConfigPassword(tt.args.ctx, tt.args.password)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
if tt.res.err != nil && !tt.res.err(err) {
|
||||
t.Errorf("got wrong err: %v ", err)
|
||||
}
|
||||
if tt.res.err == nil {
|
||||
assert.Equal(t, tt.res.want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func newSMTPConfigChangedEvent(ctx context.Context, tls bool, fromAddress, fromName, host, user string) *iam.SMTPConfigChangedEvent {
|
||||
changes := []iam.SMTPConfigChanges{
|
||||
iam.ChangeSMTPConfigTLS(tls),
|
||||
iam.ChangeSMTPConfigFromAddress(fromAddress),
|
||||
iam.ChangeSMTPConfigFromName(fromName),
|
||||
iam.ChangeSMTPConfigSMTPHost(host),
|
||||
iam.ChangeSMTPConfigSMTPUser(user),
|
||||
}
|
||||
event, _ := iam.NewSMTPConfigChangeEvent(ctx,
|
||||
&iam.NewAggregate().Aggregate,
|
||||
changes,
|
||||
)
|
||||
return event
|
||||
}
|
@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/eventstore"
|
||||
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
@ -23,7 +24,7 @@ func (c *Commands) getHuman(ctx context.Context, userID, resourceowner string) (
|
||||
return writeModelToHuman(human), nil
|
||||
}
|
||||
|
||||
func (c *Commands) AddHuman(ctx context.Context, orgID string, human *domain.Human) (*domain.Human, error) {
|
||||
func (c *Commands) AddHuman(ctx context.Context, orgID string, human *domain.Human, initCodeGenerator crypto.Generator, phoneCodeGenerator crypto.Generator) (*domain.Human, error) {
|
||||
if orgID == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-XYFk9", "Errors.ResourceOwnerMissing")
|
||||
}
|
||||
@ -35,7 +36,7 @@ func (c *Commands) AddHuman(ctx context.Context, orgID string, human *domain.Hum
|
||||
if err != nil {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(err, "COMMAND-M5Fsd", "Errors.Org.PasswordComplexity.NotFound")
|
||||
}
|
||||
events, addedHuman, err := c.addHuman(ctx, orgID, human, orgIAMPolicy, pwPolicy)
|
||||
events, addedHuman, err := c.addHuman(ctx, orgID, human, orgIAMPolicy, pwPolicy, initCodeGenerator, phoneCodeGenerator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -52,7 +53,7 @@ func (c *Commands) AddHuman(ctx context.Context, orgID string, human *domain.Hum
|
||||
return writeModelToHuman(addedHuman), nil
|
||||
}
|
||||
|
||||
func (c *Commands) ImportHuman(ctx context.Context, orgID string, human *domain.Human, passwordless bool) (_ *domain.Human, passwordlessCode *domain.PasswordlessInitCode, err error) {
|
||||
func (c *Commands) ImportHuman(ctx context.Context, orgID string, human *domain.Human, passwordless bool, initCodeGenerator crypto.Generator, phoneCodeGenerator crypto.Generator, passwordlessCodeGenerator crypto.Generator) (_ *domain.Human, passwordlessCode *domain.PasswordlessInitCode, err error) {
|
||||
if orgID == "" {
|
||||
return nil, nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-5N8fs", "Errors.ResourceOwnerMissing")
|
||||
}
|
||||
@ -64,7 +65,7 @@ func (c *Commands) ImportHuman(ctx context.Context, orgID string, human *domain.
|
||||
if err != nil {
|
||||
return nil, nil, caos_errs.ThrowPreconditionFailed(err, "COMMAND-4N8gs", "Errors.Org.PasswordComplexity.NotFound")
|
||||
}
|
||||
events, addedHuman, addedCode, code, err := c.importHuman(ctx, orgID, human, passwordless, orgIAMPolicy, pwPolicy)
|
||||
events, addedHuman, addedCode, code, err := c.importHuman(ctx, orgID, human, passwordless, orgIAMPolicy, pwPolicy, initCodeGenerator, phoneCodeGenerator, passwordlessCodeGenerator)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@ -88,27 +89,27 @@ func (c *Commands) ImportHuman(ctx context.Context, orgID string, human *domain.
|
||||
return writeModelToHuman(addedHuman), passwordlessCode, nil
|
||||
}
|
||||
|
||||
func (c *Commands) addHuman(ctx context.Context, orgID string, human *domain.Human, orgIAMPolicy *domain.OrgIAMPolicy, pwPolicy *domain.PasswordComplexityPolicy) ([]eventstore.Command, *HumanWriteModel, error) {
|
||||
func (c *Commands) addHuman(ctx context.Context, orgID string, human *domain.Human, orgIAMPolicy *domain.OrgIAMPolicy, pwPolicy *domain.PasswordComplexityPolicy, initCodeGenerator crypto.Generator, phoneCodeGenerator crypto.Generator) ([]eventstore.Command, *HumanWriteModel, error) {
|
||||
if orgID == "" || !human.IsValid() {
|
||||
return nil, nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-67Ms8", "Errors.User.Invalid")
|
||||
}
|
||||
if human.Password != nil && human.SecretString != "" {
|
||||
human.ChangeRequired = true
|
||||
}
|
||||
return c.createHuman(ctx, orgID, human, nil, false, false, orgIAMPolicy, pwPolicy)
|
||||
return c.createHuman(ctx, orgID, human, nil, false, false, orgIAMPolicy, pwPolicy, initCodeGenerator, phoneCodeGenerator)
|
||||
}
|
||||
|
||||
func (c *Commands) importHuman(ctx context.Context, orgID string, human *domain.Human, passwordless bool, orgIAMPolicy *domain.OrgIAMPolicy, pwPolicy *domain.PasswordComplexityPolicy) (events []eventstore.Command, humanWriteModel *HumanWriteModel, passwordlessCodeWriteModel *HumanPasswordlessInitCodeWriteModel, code string, err error) {
|
||||
func (c *Commands) importHuman(ctx context.Context, orgID string, human *domain.Human, passwordless bool, orgIAMPolicy *domain.OrgIAMPolicy, pwPolicy *domain.PasswordComplexityPolicy, initCodeGenerator crypto.Generator, phoneCodeGenerator crypto.Generator, passwordlessCodeGenerator crypto.Generator) (events []eventstore.Command, humanWriteModel *HumanWriteModel, passwordlessCodeWriteModel *HumanPasswordlessInitCodeWriteModel, code string, err error) {
|
||||
if orgID == "" || !human.IsValid() {
|
||||
return nil, nil, nil, "", caos_errs.ThrowInvalidArgument(nil, "COMMAND-00p2b", "Errors.User.Invalid")
|
||||
}
|
||||
events, humanWriteModel, err = c.createHuman(ctx, orgID, human, nil, false, passwordless, orgIAMPolicy, pwPolicy)
|
||||
events, humanWriteModel, err = c.createHuman(ctx, orgID, human, nil, false, passwordless, orgIAMPolicy, pwPolicy, initCodeGenerator, phoneCodeGenerator)
|
||||
if err != nil {
|
||||
return nil, nil, nil, "", err
|
||||
}
|
||||
if passwordless {
|
||||
var codeEvent eventstore.Command
|
||||
codeEvent, passwordlessCodeWriteModel, code, err = c.humanAddPasswordlessInitCode(ctx, human.AggregateID, orgID, true)
|
||||
codeEvent, passwordlessCodeWriteModel, code, err = c.humanAddPasswordlessInitCode(ctx, human.AggregateID, orgID, true, passwordlessCodeGenerator)
|
||||
if err != nil {
|
||||
return nil, nil, nil, "", err
|
||||
}
|
||||
@ -117,7 +118,7 @@ func (c *Commands) importHuman(ctx context.Context, orgID string, human *domain.
|
||||
return events, humanWriteModel, passwordlessCodeWriteModel, code, nil
|
||||
}
|
||||
|
||||
func (c *Commands) RegisterHuman(ctx context.Context, orgID string, human *domain.Human, link *domain.UserIDPLink, orgMemberRoles []string) (*domain.Human, error) {
|
||||
func (c *Commands) RegisterHuman(ctx context.Context, orgID string, human *domain.Human, link *domain.UserIDPLink, orgMemberRoles []string, initCodeGenerator crypto.Generator, phoneCodeGenerator crypto.Generator) (*domain.Human, error) {
|
||||
if orgID == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-GEdf2", "Errors.ResourceOwnerMissing")
|
||||
}
|
||||
@ -136,7 +137,7 @@ func (c *Commands) RegisterHuman(ctx context.Context, orgID string, human *domai
|
||||
if !loginPolicy.AllowRegister {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(err, "COMMAND-SAbr3", "Errors.Org.LoginPolicy.RegistrationNotAllowed")
|
||||
}
|
||||
userEvents, registeredHuman, err := c.registerHuman(ctx, orgID, human, link, orgIAMPolicy, pwPolicy)
|
||||
userEvents, registeredHuman, err := c.registerHuman(ctx, orgID, human, link, orgIAMPolicy, pwPolicy, initCodeGenerator, phoneCodeGenerator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -170,7 +171,7 @@ func (c *Commands) RegisterHuman(ctx context.Context, orgID string, human *domai
|
||||
return writeModelToHuman(registeredHuman), nil
|
||||
}
|
||||
|
||||
func (c *Commands) registerHuman(ctx context.Context, orgID string, human *domain.Human, link *domain.UserIDPLink, orgIAMPolicy *domain.OrgIAMPolicy, pwPolicy *domain.PasswordComplexityPolicy) ([]eventstore.Command, *HumanWriteModel, error) {
|
||||
func (c *Commands) registerHuman(ctx context.Context, orgID string, human *domain.Human, link *domain.UserIDPLink, orgIAMPolicy *domain.OrgIAMPolicy, pwPolicy *domain.PasswordComplexityPolicy, initCodeGenerator crypto.Generator, phoneCodeGenerator crypto.Generator) ([]eventstore.Command, *HumanWriteModel, error) {
|
||||
if human != nil && human.Username == "" {
|
||||
human.Username = human.EmailAddress
|
||||
}
|
||||
@ -180,10 +181,10 @@ func (c *Commands) registerHuman(ctx context.Context, orgID string, human *domai
|
||||
if human.Password != nil && human.SecretString != "" {
|
||||
human.ChangeRequired = false
|
||||
}
|
||||
return c.createHuman(ctx, orgID, human, link, true, false, orgIAMPolicy, pwPolicy)
|
||||
return c.createHuman(ctx, orgID, human, link, true, false, orgIAMPolicy, pwPolicy, initCodeGenerator, phoneCodeGenerator)
|
||||
}
|
||||
|
||||
func (c *Commands) createHuman(ctx context.Context, orgID string, human *domain.Human, link *domain.UserIDPLink, selfregister, passwordless bool, orgIAMPolicy *domain.OrgIAMPolicy, pwPolicy *domain.PasswordComplexityPolicy) ([]eventstore.Command, *HumanWriteModel, error) {
|
||||
func (c *Commands) createHuman(ctx context.Context, orgID string, human *domain.Human, link *domain.UserIDPLink, selfregister, passwordless bool, orgIAMPolicy *domain.OrgIAMPolicy, pwPolicy *domain.PasswordComplexityPolicy, initCodeGenerator crypto.Generator, phoneCodeGenerator crypto.Generator) ([]eventstore.Command, *HumanWriteModel, error) {
|
||||
if err := human.CheckOrgIAMPolicy(orgIAMPolicy); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@ -232,7 +233,7 @@ func (c *Commands) createHuman(ctx context.Context, orgID string, human *domain.
|
||||
}
|
||||
|
||||
if human.IsInitialState(passwordless, link != nil) {
|
||||
initCode, err := domain.NewInitUserCode(c.initializeUserCode)
|
||||
initCode, err := domain.NewInitUserCode(initCodeGenerator)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@ -244,7 +245,7 @@ func (c *Commands) createHuman(ctx context.Context, orgID string, human *domain.
|
||||
}
|
||||
|
||||
if human.Phone != nil && human.PhoneNumber != "" && !human.IsPhoneVerified {
|
||||
phoneCode, err := domain.NewPhoneCode(c.phoneVerificationCode)
|
||||
phoneCode, err := domain.NewPhoneCode(phoneCodeGenerator)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ import (
|
||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||
)
|
||||
|
||||
func (c *Commands) ChangeHumanEmail(ctx context.Context, email *domain.Email) (*domain.Email, error) {
|
||||
func (c *Commands) ChangeHumanEmail(ctx context.Context, email *domain.Email, emailCodeGenerator crypto.Generator) (*domain.Email, error) {
|
||||
if !email.IsValid() || email.AggregateID == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-4M9sf", "Errors.Email.Invalid")
|
||||
}
|
||||
@ -38,7 +38,7 @@ func (c *Commands) ChangeHumanEmail(ctx context.Context, email *domain.Email) (*
|
||||
if email.IsEmailVerified {
|
||||
events = append(events, user.NewHumanEmailVerifiedEvent(ctx, userAgg))
|
||||
} else {
|
||||
emailCode, err := domain.NewEmailCode(c.emailVerificationCode)
|
||||
emailCode, err := domain.NewEmailCode(emailCodeGenerator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -56,7 +56,7 @@ func (c *Commands) ChangeHumanEmail(ctx context.Context, email *domain.Email) (*
|
||||
return writeModelToEmail(existingEmail), nil
|
||||
}
|
||||
|
||||
func (c *Commands) VerifyHumanEmail(ctx context.Context, userID, code, resourceowner string) (*domain.ObjectDetails, error) {
|
||||
func (c *Commands) VerifyHumanEmail(ctx context.Context, userID, code, resourceowner string, emailCodeGenerator crypto.Generator) (*domain.ObjectDetails, error) {
|
||||
if userID == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-4M0ds", "Errors.User.UserIDMissing")
|
||||
}
|
||||
@ -73,7 +73,7 @@ func (c *Commands) VerifyHumanEmail(ctx context.Context, userID, code, resourceo
|
||||
}
|
||||
|
||||
userAgg := UserAggregateFromWriteModel(&existingCode.WriteModel)
|
||||
err = crypto.VerifyCode(existingCode.CodeCreationDate, existingCode.CodeExpiry, existingCode.Code, code, c.emailVerificationCode)
|
||||
err = crypto.VerifyCode(existingCode.CodeCreationDate, existingCode.CodeExpiry, existingCode.Code, code, emailCodeGenerator)
|
||||
if err == nil {
|
||||
pushedEvents, err := c.eventstore.Push(ctx, user.NewHumanEmailVerifiedEvent(ctx, userAgg))
|
||||
if err != nil {
|
||||
@ -91,7 +91,7 @@ func (c *Commands) VerifyHumanEmail(ctx context.Context, userID, code, resourceo
|
||||
return nil, caos_errs.ThrowInvalidArgument(err, "COMMAND-Gdsgs", "Errors.User.Code.Invalid")
|
||||
}
|
||||
|
||||
func (c *Commands) CreateHumanEmailVerificationCode(ctx context.Context, userID, resourceOwner string) (*domain.ObjectDetails, error) {
|
||||
func (c *Commands) CreateHumanEmailVerificationCode(ctx context.Context, userID, resourceOwner string, emailCodeGenerator crypto.Generator) (*domain.ObjectDetails, error) {
|
||||
if userID == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-4M0ds", "Errors.User.UserIDMissing")
|
||||
}
|
||||
@ -110,7 +110,7 @@ func (c *Commands) CreateHumanEmailVerificationCode(ctx context.Context, userID,
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-3M9ds", "Errors.User.Email.AlreadyVerified")
|
||||
}
|
||||
userAgg := UserAggregateFromWriteModel(&existingEmail.WriteModel)
|
||||
emailCode, err := domain.NewEmailCode(c.emailVerificationCode)
|
||||
emailCode, err := domain.NewEmailCode(emailCodeGenerator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -19,13 +19,13 @@ import (
|
||||
|
||||
func TestCommandSide_ChangeHumanEmail(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
secretGenerator crypto.Generator
|
||||
eventstore *eventstore.Eventstore
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
email *domain.Email
|
||||
resourceOwner string
|
||||
ctx context.Context
|
||||
email *domain.Email
|
||||
resourceOwner string
|
||||
secretGenerator crypto.Generator
|
||||
}
|
||||
type res struct {
|
||||
want *domain.Email
|
||||
@ -263,7 +263,6 @@ func TestCommandSide_ChangeHumanEmail(t *testing.T) {
|
||||
},
|
||||
),
|
||||
),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
@ -273,7 +272,8 @@ func TestCommandSide_ChangeHumanEmail(t *testing.T) {
|
||||
},
|
||||
EmailAddress: "email-changed@test.ch",
|
||||
},
|
||||
resourceOwner: "org1",
|
||||
resourceOwner: "org1",
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
res: res{
|
||||
want: &domain.Email{
|
||||
@ -289,10 +289,9 @@ func TestCommandSide_ChangeHumanEmail(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
emailVerificationCode: tt.fields.secretGenerator,
|
||||
eventstore: tt.fields.eventstore,
|
||||
}
|
||||
got, err := r.ChangeHumanEmail(tt.args.ctx, tt.args.email)
|
||||
got, err := r.ChangeHumanEmail(tt.args.ctx, tt.args.email, tt.args.secretGenerator)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
@ -308,14 +307,14 @@ func TestCommandSide_ChangeHumanEmail(t *testing.T) {
|
||||
|
||||
func TestCommandSide_VerifyHumanEmail(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
secretGenerator crypto.Generator
|
||||
eventstore *eventstore.Eventstore
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
userID string
|
||||
code string
|
||||
resourceOwner string
|
||||
ctx context.Context
|
||||
userID string
|
||||
code string
|
||||
resourceOwner string
|
||||
secretGenerator crypto.Generator
|
||||
}
|
||||
type res struct {
|
||||
want *domain.ObjectDetails
|
||||
@ -453,13 +452,13 @@ func TestCommandSide_VerifyHumanEmail(t *testing.T) {
|
||||
},
|
||||
),
|
||||
),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
userID: "user1",
|
||||
code: "test",
|
||||
resourceOwner: "org1",
|
||||
ctx: context.Background(),
|
||||
userID: "user1",
|
||||
code: "test",
|
||||
resourceOwner: "org1",
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsErrorInvalidArgument,
|
||||
@ -508,13 +507,13 @@ func TestCommandSide_VerifyHumanEmail(t *testing.T) {
|
||||
},
|
||||
),
|
||||
),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
userID: "user1",
|
||||
code: "a",
|
||||
resourceOwner: "org1",
|
||||
ctx: context.Background(),
|
||||
userID: "user1",
|
||||
code: "a",
|
||||
resourceOwner: "org1",
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
@ -526,10 +525,9 @@ func TestCommandSide_VerifyHumanEmail(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
emailVerificationCode: tt.fields.secretGenerator,
|
||||
eventstore: tt.fields.eventstore,
|
||||
}
|
||||
got, err := r.VerifyHumanEmail(tt.args.ctx, tt.args.userID, tt.args.code, tt.args.resourceOwner)
|
||||
got, err := r.VerifyHumanEmail(tt.args.ctx, tt.args.userID, tt.args.code, tt.args.resourceOwner, tt.args.secretGenerator)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
@ -545,13 +543,13 @@ func TestCommandSide_VerifyHumanEmail(t *testing.T) {
|
||||
|
||||
func TestCommandSide_CreateVerificationCodeHumanEmail(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
secretGenerator crypto.Generator
|
||||
eventstore *eventstore.Eventstore
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
userID string
|
||||
resourceOwner string
|
||||
ctx context.Context
|
||||
userID string
|
||||
resourceOwner string
|
||||
secretGenerator crypto.Generator
|
||||
}
|
||||
type res struct {
|
||||
want *domain.ObjectDetails
|
||||
@ -719,12 +717,12 @@ func TestCommandSide_CreateVerificationCodeHumanEmail(t *testing.T) {
|
||||
},
|
||||
),
|
||||
),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
userID: "user1",
|
||||
resourceOwner: "org1",
|
||||
ctx: context.Background(),
|
||||
userID: "user1",
|
||||
resourceOwner: "org1",
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
@ -736,10 +734,9 @@ func TestCommandSide_CreateVerificationCodeHumanEmail(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
emailVerificationCode: tt.fields.secretGenerator,
|
||||
eventstore: tt.fields.eventstore,
|
||||
}
|
||||
got, err := r.CreateHumanEmailVerificationCode(tt.args.ctx, tt.args.userID, tt.args.resourceOwner)
|
||||
got, err := r.CreateHumanEmailVerificationCode(tt.args.ctx, tt.args.userID, tt.args.resourceOwner, tt.args.secretGenerator)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ import (
|
||||
)
|
||||
|
||||
//ResendInitialMail resend inital mail and changes email if provided
|
||||
func (c *Commands) ResendInitialMail(ctx context.Context, userID, email, resourceOwner string) (objectDetails *domain.ObjectDetails, err error) {
|
||||
func (c *Commands) ResendInitialMail(ctx context.Context, userID, email, resourceOwner string, initCodeGenerator crypto.Generator) (objectDetails *domain.ObjectDetails, err error) {
|
||||
if userID == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-2n8vs", "Errors.User.UserIDMissing")
|
||||
}
|
||||
@ -33,7 +33,7 @@ func (c *Commands) ResendInitialMail(ctx context.Context, userID, email, resourc
|
||||
changedEvent, _ := existingCode.NewChangedEvent(ctx, userAgg, email)
|
||||
events = append(events, changedEvent)
|
||||
}
|
||||
initCode, err := domain.NewInitUserCode(c.initializeUserCode)
|
||||
initCode, err := domain.NewInitUserCode(initCodeGenerator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -49,7 +49,7 @@ func (c *Commands) ResendInitialMail(ctx context.Context, userID, email, resourc
|
||||
return writeModelToObjectDetails(&existingCode.WriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) HumanVerifyInitCode(ctx context.Context, userID, resourceOwner, code, passwordString string) error {
|
||||
func (c *Commands) HumanVerifyInitCode(ctx context.Context, userID, resourceOwner, code, passwordString string, initCodeGenerator crypto.Generator) error {
|
||||
if userID == "" {
|
||||
return caos_errs.ThrowInvalidArgument(nil, "COMMAND-mkM9f", "Errors.User.UserIDMissing")
|
||||
}
|
||||
@ -66,7 +66,7 @@ func (c *Commands) HumanVerifyInitCode(ctx context.Context, userID, resourceOwne
|
||||
}
|
||||
|
||||
userAgg := UserAggregateFromWriteModel(&existingCode.WriteModel)
|
||||
err = crypto.VerifyCode(existingCode.CodeCreationDate, existingCode.CodeExpiry, existingCode.Code, code, c.initializeUserCode)
|
||||
err = crypto.VerifyCode(existingCode.CodeCreationDate, existingCode.CodeExpiry, existingCode.Code, code, initCodeGenerator)
|
||||
if err != nil {
|
||||
_, err = c.eventstore.Push(ctx, user.NewHumanInitializedCheckFailedEvent(ctx, userAgg))
|
||||
logging.LogWithFields("COMMAND-Dg2z5", "userID", userAgg.ID).OnError(err).Error("NewHumanInitializedCheckFailedEvent push failed")
|
||||
|
@ -20,14 +20,14 @@ import (
|
||||
|
||||
func TestCommandSide_ResendInitialMail(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
secretGenerator crypto.Generator
|
||||
eventstore *eventstore.Eventstore
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
userID string
|
||||
email string
|
||||
resourceOwner string
|
||||
ctx context.Context
|
||||
userID string
|
||||
email string
|
||||
resourceOwner string
|
||||
secretGenerator crypto.Generator
|
||||
}
|
||||
type res struct {
|
||||
want *domain.ObjectDetails
|
||||
@ -150,13 +150,13 @@ func TestCommandSide_ResendInitialMail(t *testing.T) {
|
||||
},
|
||||
),
|
||||
),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
userID: "user1",
|
||||
resourceOwner: "org1",
|
||||
email: "email@test.ch",
|
||||
ctx: context.Background(),
|
||||
userID: "user1",
|
||||
resourceOwner: "org1",
|
||||
email: "email@test.ch",
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
@ -208,12 +208,12 @@ func TestCommandSide_ResendInitialMail(t *testing.T) {
|
||||
},
|
||||
),
|
||||
),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
userID: "user1",
|
||||
resourceOwner: "org1",
|
||||
ctx: context.Background(),
|
||||
userID: "user1",
|
||||
resourceOwner: "org1",
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
@ -269,13 +269,13 @@ func TestCommandSide_ResendInitialMail(t *testing.T) {
|
||||
},
|
||||
),
|
||||
),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
userID: "user1",
|
||||
resourceOwner: "org1",
|
||||
email: "email2@test.ch",
|
||||
ctx: context.Background(),
|
||||
userID: "user1",
|
||||
resourceOwner: "org1",
|
||||
email: "email2@test.ch",
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
@ -287,10 +287,9 @@ func TestCommandSide_ResendInitialMail(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
initializeUserCode: tt.fields.secretGenerator,
|
||||
eventstore: tt.fields.eventstore,
|
||||
}
|
||||
got, err := r.ResendInitialMail(tt.args.ctx, tt.args.userID, tt.args.email, tt.args.resourceOwner)
|
||||
got, err := r.ResendInitialMail(tt.args.ctx, tt.args.userID, tt.args.email, tt.args.resourceOwner, tt.args.secretGenerator)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
@ -307,15 +306,15 @@ func TestCommandSide_ResendInitialMail(t *testing.T) {
|
||||
func TestCommandSide_VerifyInitCode(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
secretGenerator crypto.Generator
|
||||
userPasswordAlg crypto.HashAlgorithm
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
userID string
|
||||
code string
|
||||
resourceOwner string
|
||||
password string
|
||||
ctx context.Context
|
||||
userID string
|
||||
code string
|
||||
resourceOwner string
|
||||
password string
|
||||
secretGenerator crypto.Generator
|
||||
}
|
||||
type res struct {
|
||||
want *domain.ObjectDetails
|
||||
@ -453,13 +452,13 @@ func TestCommandSide_VerifyInitCode(t *testing.T) {
|
||||
},
|
||||
),
|
||||
),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
userID: "user1",
|
||||
code: "test",
|
||||
resourceOwner: "org1",
|
||||
ctx: context.Background(),
|
||||
userID: "user1",
|
||||
code: "test",
|
||||
resourceOwner: "org1",
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsErrorInvalidArgument,
|
||||
@ -513,13 +512,13 @@ func TestCommandSide_VerifyInitCode(t *testing.T) {
|
||||
},
|
||||
),
|
||||
),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
userID: "user1",
|
||||
code: "a",
|
||||
resourceOwner: "org1",
|
||||
ctx: context.Background(),
|
||||
userID: "user1",
|
||||
code: "a",
|
||||
resourceOwner: "org1",
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
@ -596,15 +595,15 @@ func TestCommandSide_VerifyInitCode(t *testing.T) {
|
||||
},
|
||||
),
|
||||
),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
userPasswordAlg: crypto.CreateMockHashAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
userID: "user1",
|
||||
code: "a",
|
||||
resourceOwner: "org1",
|
||||
password: "password",
|
||||
ctx: context.Background(),
|
||||
userID: "user1",
|
||||
code: "a",
|
||||
resourceOwner: "org1",
|
||||
password: "password",
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
@ -616,11 +615,10 @@ func TestCommandSide_VerifyInitCode(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
initializeUserCode: tt.fields.secretGenerator,
|
||||
userPasswordAlg: tt.fields.userPasswordAlg,
|
||||
eventstore: tt.fields.eventstore,
|
||||
userPasswordAlg: tt.fields.userPasswordAlg,
|
||||
}
|
||||
err := r.HumanVerifyInitCode(tt.args.ctx, tt.args.userID, tt.args.resourceOwner, tt.args.code, tt.args.password)
|
||||
err := r.HumanVerifyInitCode(tt.args.ctx, tt.args.userID, tt.args.resourceOwner, tt.args.code, tt.args.password, tt.args.secretGenerator)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ func (c *Commands) SetPassword(ctx context.Context, orgID, userID, passwordStrin
|
||||
return writeModelToObjectDetails(&existingPassword.WriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) SetPasswordWithVerifyCode(ctx context.Context, orgID, userID, code, passwordString, userAgentID string) (err error) {
|
||||
func (c *Commands) SetPasswordWithVerifyCode(ctx context.Context, orgID, userID, code, passwordString, userAgentID string, passwordVerificationCode crypto.Generator) (err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
||||
@ -65,7 +65,7 @@ func (c *Commands) SetPasswordWithVerifyCode(ctx context.Context, orgID, userID,
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-2M9fs", "Errors.User.Code.NotFound")
|
||||
}
|
||||
|
||||
err = crypto.VerifyCode(existingCode.CodeCreationDate, existingCode.CodeExpiry, existingCode.Code, code, c.passwordVerificationCode)
|
||||
err = crypto.VerifyCode(existingCode.CodeCreationDate, existingCode.CodeExpiry, existingCode.Code, code, passwordVerificationCode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -148,7 +148,7 @@ func (c *Commands) changePassword(ctx context.Context, userAgentID string, passw
|
||||
return user.NewHumanPasswordChangedEvent(ctx, userAgg, password.SecretCrypto, password.ChangeRequired, userAgentID), nil
|
||||
}
|
||||
|
||||
func (c *Commands) RequestSetPassword(ctx context.Context, userID, resourceOwner string, notifyType domain.NotificationType) (objectDetails *domain.ObjectDetails, err error) {
|
||||
func (c *Commands) RequestSetPassword(ctx context.Context, userID, resourceOwner string, notifyType domain.NotificationType, passwordVerificationCode crypto.Generator) (objectDetails *domain.ObjectDetails, err error) {
|
||||
if userID == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-M00oL", "Errors.User.UserIDMissing")
|
||||
}
|
||||
@ -164,7 +164,7 @@ func (c *Commands) RequestSetPassword(ctx context.Context, userID, resourceOwner
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-2M9sd", "Errors.User.NotInitialised")
|
||||
}
|
||||
userAgg := UserAggregateFromWriteModel(&existingHuman.WriteModel)
|
||||
passwordCode, err := domain.NewPasswordCode(c.passwordVerificationCode)
|
||||
passwordCode, err := domain.NewPasswordCode(passwordVerificationCode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -239,15 +239,15 @@ func TestCommandSide_SetPassword(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
userPasswordAlg crypto.HashAlgorithm
|
||||
secretGenerator crypto.Generator
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
userID string
|
||||
code string
|
||||
resourceOwner string
|
||||
password string
|
||||
agentID string
|
||||
ctx context.Context
|
||||
userID string
|
||||
code string
|
||||
resourceOwner string
|
||||
password string
|
||||
agentID string
|
||||
secretGenerator crypto.Generator
|
||||
}
|
||||
type res struct {
|
||||
want *domain.ObjectDetails
|
||||
@ -377,14 +377,14 @@ func TestCommandSide_SetPassword(t *testing.T) {
|
||||
),
|
||||
),
|
||||
),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
userID: "user1",
|
||||
code: "test",
|
||||
resourceOwner: "org1",
|
||||
password: "password",
|
||||
ctx: context.Background(),
|
||||
userID: "user1",
|
||||
code: "test",
|
||||
resourceOwner: "org1",
|
||||
password: "password",
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsPreconditionFailed,
|
||||
@ -459,15 +459,15 @@ func TestCommandSide_SetPassword(t *testing.T) {
|
||||
},
|
||||
),
|
||||
),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
userPasswordAlg: crypto.CreateMockHashAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
userID: "user1",
|
||||
resourceOwner: "org1",
|
||||
password: "password",
|
||||
code: "a",
|
||||
ctx: context.Background(),
|
||||
userID: "user1",
|
||||
resourceOwner: "org1",
|
||||
password: "password",
|
||||
code: "a",
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
@ -479,11 +479,10 @@ func TestCommandSide_SetPassword(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
userPasswordAlg: tt.fields.userPasswordAlg,
|
||||
passwordVerificationCode: tt.fields.secretGenerator,
|
||||
eventstore: tt.fields.eventstore,
|
||||
userPasswordAlg: tt.fields.userPasswordAlg,
|
||||
}
|
||||
err := r.SetPasswordWithVerifyCode(tt.args.ctx, tt.args.resourceOwner, tt.args.userID, tt.args.code, tt.args.password, tt.args.agentID)
|
||||
err := r.SetPasswordWithVerifyCode(tt.args.ctx, tt.args.resourceOwner, tt.args.userID, tt.args.code, tt.args.password, tt.args.agentID, tt.args.secretGenerator)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
@ -778,14 +777,14 @@ func TestCommandSide_ChangePassword(t *testing.T) {
|
||||
|
||||
func TestCommandSide_RequestSetPassword(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
secretGenerator crypto.Generator
|
||||
eventstore *eventstore.Eventstore
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
userID string
|
||||
resourceOwner string
|
||||
notifyType domain.NotificationType
|
||||
ctx context.Context
|
||||
userID string
|
||||
resourceOwner string
|
||||
notifyType domain.NotificationType
|
||||
secretGenerator crypto.Generator
|
||||
}
|
||||
type res struct {
|
||||
want *domain.ObjectDetails
|
||||
@ -925,12 +924,12 @@ func TestCommandSide_RequestSetPassword(t *testing.T) {
|
||||
},
|
||||
),
|
||||
),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
userID: "user1",
|
||||
resourceOwner: "org1",
|
||||
ctx: context.Background(),
|
||||
userID: "user1",
|
||||
resourceOwner: "org1",
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
@ -942,10 +941,9 @@ func TestCommandSide_RequestSetPassword(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
passwordVerificationCode: tt.fields.secretGenerator,
|
||||
eventstore: tt.fields.eventstore,
|
||||
}
|
||||
got, err := r.RequestSetPassword(tt.args.ctx, tt.args.userID, tt.args.resourceOwner, tt.args.notifyType)
|
||||
got, err := r.RequestSetPassword(tt.args.ctx, tt.args.userID, tt.args.resourceOwner, tt.args.notifyType, tt.args.secretGenerator)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ import (
|
||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||
)
|
||||
|
||||
func (c *Commands) ChangeHumanPhone(ctx context.Context, phone *domain.Phone, resourceOwner string) (*domain.Phone, error) {
|
||||
func (c *Commands) ChangeHumanPhone(ctx context.Context, phone *domain.Phone, resourceOwner string, phoneCodeGenerator crypto.Generator) (*domain.Phone, error) {
|
||||
if !phone.IsValid() {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-6M0ds", "Errors.Phone.Invalid")
|
||||
}
|
||||
@ -36,7 +36,7 @@ func (c *Commands) ChangeHumanPhone(ctx context.Context, phone *domain.Phone, re
|
||||
if phone.IsPhoneVerified {
|
||||
events = append(events, user.NewHumanPhoneVerifiedEvent(ctx, userAgg))
|
||||
} else {
|
||||
phoneCode, err := domain.NewPhoneCode(c.phoneVerificationCode)
|
||||
phoneCode, err := domain.NewPhoneCode(phoneCodeGenerator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -55,7 +55,7 @@ func (c *Commands) ChangeHumanPhone(ctx context.Context, phone *domain.Phone, re
|
||||
return writeModelToPhone(existingPhone), nil
|
||||
}
|
||||
|
||||
func (c *Commands) VerifyHumanPhone(ctx context.Context, userID, code, resourceowner string) (*domain.ObjectDetails, error) {
|
||||
func (c *Commands) VerifyHumanPhone(ctx context.Context, userID, code, resourceowner string, phoneCodeGenerator crypto.Generator) (*domain.ObjectDetails, error) {
|
||||
if userID == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-Km9ds", "Errors.User.UserIDMissing")
|
||||
}
|
||||
@ -75,7 +75,7 @@ func (c *Commands) VerifyHumanPhone(ctx context.Context, userID, code, resourceo
|
||||
}
|
||||
|
||||
userAgg := UserAggregateFromWriteModel(&existingCode.WriteModel)
|
||||
err = crypto.VerifyCode(existingCode.CodeCreationDate, existingCode.CodeExpiry, existingCode.Code, code, c.phoneVerificationCode)
|
||||
err = crypto.VerifyCode(existingCode.CodeCreationDate, existingCode.CodeExpiry, existingCode.Code, code, phoneCodeGenerator)
|
||||
if err == nil {
|
||||
pushedEvents, err := c.eventstore.Push(ctx, user.NewHumanPhoneVerifiedEvent(ctx, userAgg))
|
||||
if err != nil {
|
||||
@ -92,7 +92,7 @@ func (c *Commands) VerifyHumanPhone(ctx context.Context, userID, code, resourceo
|
||||
return nil, caos_errs.ThrowInvalidArgument(err, "COMMAND-sM0cs", "Errors.User.Code.Invalid")
|
||||
}
|
||||
|
||||
func (c *Commands) CreateHumanPhoneVerificationCode(ctx context.Context, userID, resourceowner string) (*domain.ObjectDetails, error) {
|
||||
func (c *Commands) CreateHumanPhoneVerificationCode(ctx context.Context, userID, resourceowner string, phoneCodeGenerator crypto.Generator) (*domain.ObjectDetails, error) {
|
||||
if userID == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-4M0ds", "Errors.User.UserIDMissing")
|
||||
}
|
||||
@ -112,7 +112,7 @@ func (c *Commands) CreateHumanPhoneVerificationCode(ctx context.Context, userID,
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-2M9sf", "Errors.User.Phone.AlreadyVerified")
|
||||
}
|
||||
|
||||
phoneCode, err := domain.NewPhoneCode(c.phoneVerificationCode)
|
||||
phoneCode, err := domain.NewPhoneCode(phoneCodeGenerator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -19,13 +19,13 @@ import (
|
||||
|
||||
func TestCommandSide_ChangeHumanPhone(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
secretGenerator crypto.Generator
|
||||
eventstore *eventstore.Eventstore
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
email *domain.Phone
|
||||
resourceOwner string
|
||||
ctx context.Context
|
||||
email *domain.Phone
|
||||
resourceOwner string
|
||||
secretGenerator crypto.Generator
|
||||
}
|
||||
type res struct {
|
||||
want *domain.Phone
|
||||
@ -232,7 +232,6 @@ func TestCommandSide_ChangeHumanPhone(t *testing.T) {
|
||||
},
|
||||
),
|
||||
),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
@ -242,7 +241,8 @@ func TestCommandSide_ChangeHumanPhone(t *testing.T) {
|
||||
},
|
||||
PhoneNumber: "0711234567",
|
||||
},
|
||||
resourceOwner: "org1",
|
||||
resourceOwner: "org1",
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
res: res{
|
||||
want: &domain.Phone{
|
||||
@ -258,10 +258,9 @@ func TestCommandSide_ChangeHumanPhone(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
phoneVerificationCode: tt.fields.secretGenerator,
|
||||
eventstore: tt.fields.eventstore,
|
||||
}
|
||||
got, err := r.ChangeHumanPhone(tt.args.ctx, tt.args.email, tt.args.resourceOwner)
|
||||
got, err := r.ChangeHumanPhone(tt.args.ctx, tt.args.email, tt.args.resourceOwner, tt.args.secretGenerator)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
@ -277,14 +276,14 @@ func TestCommandSide_ChangeHumanPhone(t *testing.T) {
|
||||
|
||||
func TestCommandSide_VerifyHumanPhone(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
secretGenerator crypto.Generator
|
||||
eventstore *eventstore.Eventstore
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
userID string
|
||||
code string
|
||||
resourceOwner string
|
||||
ctx context.Context
|
||||
userID string
|
||||
code string
|
||||
resourceOwner string
|
||||
secretGenerator crypto.Generator
|
||||
}
|
||||
type res struct {
|
||||
want *domain.ObjectDetails
|
||||
@ -428,13 +427,13 @@ func TestCommandSide_VerifyHumanPhone(t *testing.T) {
|
||||
},
|
||||
),
|
||||
),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
userID: "user1",
|
||||
code: "test",
|
||||
resourceOwner: "org1",
|
||||
ctx: context.Background(),
|
||||
userID: "user1",
|
||||
code: "test",
|
||||
resourceOwner: "org1",
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsErrorInvalidArgument,
|
||||
@ -489,13 +488,13 @@ func TestCommandSide_VerifyHumanPhone(t *testing.T) {
|
||||
},
|
||||
),
|
||||
),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
userID: "user1",
|
||||
code: "a",
|
||||
resourceOwner: "org1",
|
||||
ctx: context.Background(),
|
||||
userID: "user1",
|
||||
code: "a",
|
||||
resourceOwner: "org1",
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
@ -507,10 +506,9 @@ func TestCommandSide_VerifyHumanPhone(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
phoneVerificationCode: tt.fields.secretGenerator,
|
||||
eventstore: tt.fields.eventstore,
|
||||
}
|
||||
got, err := r.VerifyHumanPhone(tt.args.ctx, tt.args.userID, tt.args.code, tt.args.resourceOwner)
|
||||
got, err := r.VerifyHumanPhone(tt.args.ctx, tt.args.userID, tt.args.code, tt.args.resourceOwner, tt.args.secretGenerator)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
@ -526,13 +524,13 @@ func TestCommandSide_VerifyHumanPhone(t *testing.T) {
|
||||
|
||||
func TestCommandSide_CreateVerificationCodeHumanPhone(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
secretGenerator crypto.Generator
|
||||
eventstore *eventstore.Eventstore
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
userID string
|
||||
resourceOwner string
|
||||
ctx context.Context
|
||||
userID string
|
||||
resourceOwner string
|
||||
secretGenerator crypto.Generator
|
||||
}
|
||||
type res struct {
|
||||
want *domain.ObjectDetails
|
||||
@ -663,12 +661,12 @@ func TestCommandSide_CreateVerificationCodeHumanPhone(t *testing.T) {
|
||||
},
|
||||
),
|
||||
),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
userID: "user1",
|
||||
resourceOwner: "org1",
|
||||
ctx: context.Background(),
|
||||
userID: "user1",
|
||||
resourceOwner: "org1",
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
res: res{
|
||||
want: &domain.ObjectDetails{
|
||||
@ -680,10 +678,9 @@ func TestCommandSide_CreateVerificationCodeHumanPhone(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
phoneVerificationCode: tt.fields.secretGenerator,
|
||||
eventstore: tt.fields.eventstore,
|
||||
}
|
||||
got, err := r.CreateHumanPhoneVerificationCode(tt.args.ctx, tt.args.userID, tt.args.resourceOwner)
|
||||
got, err := r.CreateHumanPhoneVerificationCode(tt.args.ctx, tt.args.userID, tt.args.resourceOwner, tt.args.secretGenerator)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
@ -25,13 +25,13 @@ func TestCommandSide_AddHuman(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
idGenerator id.Generator
|
||||
secretGenerator crypto.Generator
|
||||
userPasswordAlg crypto.HashAlgorithm
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
orgID string
|
||||
human *domain.Human
|
||||
ctx context.Context
|
||||
orgID string
|
||||
human *domain.Human
|
||||
secretGenerator crypto.Generator
|
||||
}
|
||||
type res struct {
|
||||
want *domain.Human
|
||||
@ -228,8 +228,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
|
||||
uniqueConstraintsFromEventConstraint(user.NewAddUsernameUniqueConstraint("username", "org1", true)),
|
||||
),
|
||||
),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
@ -244,6 +243,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
|
||||
EmailAddress: "email@test.ch",
|
||||
},
|
||||
},
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
res: res{
|
||||
want: &domain.Human{
|
||||
@ -312,7 +312,6 @@ func TestCommandSide_AddHuman(t *testing.T) {
|
||||
),
|
||||
),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
userPasswordAlg: crypto.CreateMockHashAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
@ -331,6 +330,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
|
||||
EmailAddress: "email@test.ch",
|
||||
},
|
||||
},
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
res: res{
|
||||
want: &domain.Human{
|
||||
@ -391,7 +391,6 @@ func TestCommandSide_AddHuman(t *testing.T) {
|
||||
),
|
||||
),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
userPasswordAlg: crypto.CreateMockHashAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
@ -411,6 +410,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
|
||||
IsEmailVerified: true,
|
||||
},
|
||||
},
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
res: res{
|
||||
want: &domain.Human{
|
||||
@ -489,8 +489,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
|
||||
uniqueConstraintsFromEventConstraint(user.NewAddUsernameUniqueConstraint("username", "org1", true)),
|
||||
),
|
||||
),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
@ -508,6 +507,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
|
||||
PhoneNumber: "+41711234567",
|
||||
},
|
||||
},
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
res: res{
|
||||
want: &domain.Human{
|
||||
@ -582,8 +582,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
|
||||
uniqueConstraintsFromEventConstraint(user.NewAddUsernameUniqueConstraint("username", "org1", true)),
|
||||
),
|
||||
),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
@ -602,6 +601,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
|
||||
IsPhoneVerified: true,
|
||||
},
|
||||
},
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
res: res{
|
||||
want: &domain.Human{
|
||||
@ -630,13 +630,11 @@ func TestCommandSide_AddHuman(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
idGenerator: tt.fields.idGenerator,
|
||||
initializeUserCode: tt.fields.secretGenerator,
|
||||
phoneVerificationCode: tt.fields.secretGenerator,
|
||||
userPasswordAlg: tt.fields.userPasswordAlg,
|
||||
eventstore: tt.fields.eventstore,
|
||||
idGenerator: tt.fields.idGenerator,
|
||||
userPasswordAlg: tt.fields.userPasswordAlg,
|
||||
}
|
||||
got, err := r.AddHuman(tt.args.ctx, tt.args.orgID, tt.args.human)
|
||||
got, err := r.AddHuman(tt.args.ctx, tt.args.orgID, tt.args.human, tt.args.secretGenerator, tt.args.secretGenerator)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
@ -652,17 +650,17 @@ func TestCommandSide_AddHuman(t *testing.T) {
|
||||
|
||||
func TestCommandSide_ImportHuman(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
idGenerator id.Generator
|
||||
secretGenerator crypto.Generator
|
||||
userPasswordAlg crypto.HashAlgorithm
|
||||
passwordlessInitCode crypto.Generator
|
||||
eventstore *eventstore.Eventstore
|
||||
idGenerator id.Generator
|
||||
userPasswordAlg crypto.HashAlgorithm
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
orgID string
|
||||
human *domain.Human
|
||||
passwordless bool
|
||||
ctx context.Context
|
||||
orgID string
|
||||
human *domain.Human
|
||||
passwordless bool
|
||||
secretGenerator crypto.Generator
|
||||
passwordlessInitCode crypto.Generator
|
||||
}
|
||||
type res struct {
|
||||
wantHuman *domain.Human
|
||||
@ -850,7 +848,6 @@ func TestCommandSide_ImportHuman(t *testing.T) {
|
||||
),
|
||||
),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
userPasswordAlg: crypto.CreateMockHashAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
@ -870,6 +867,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
|
||||
EmailAddress: "email@test.ch",
|
||||
},
|
||||
},
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
res: res{
|
||||
wantHuman: &domain.Human{
|
||||
@ -930,7 +928,6 @@ func TestCommandSide_ImportHuman(t *testing.T) {
|
||||
),
|
||||
),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
userPasswordAlg: crypto.CreateMockHashAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
@ -951,6 +948,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
|
||||
IsEmailVerified: true,
|
||||
},
|
||||
},
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
res: res{
|
||||
wantHuman: &domain.Human{
|
||||
@ -1025,10 +1023,8 @@ func TestCommandSide_ImportHuman(t *testing.T) {
|
||||
uniqueConstraintsFromEventConstraint(user.NewAddUsernameUniqueConstraint("username", "org1", true)),
|
||||
),
|
||||
),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1", "code1"),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
userPasswordAlg: crypto.CreateMockHashAlg(gomock.NewController(t)),
|
||||
passwordlessInitCode: GetMockSecretGenerator(t),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1", "code1"),
|
||||
userPasswordAlg: crypto.CreateMockHashAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
@ -1044,7 +1040,9 @@ func TestCommandSide_ImportHuman(t *testing.T) {
|
||||
IsEmailVerified: true,
|
||||
},
|
||||
},
|
||||
passwordless: true,
|
||||
passwordless: true,
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
passwordlessInitCode: GetMockSecretGenerator(t),
|
||||
},
|
||||
res: res{
|
||||
wantHuman: &domain.Human{
|
||||
@ -1129,10 +1127,8 @@ func TestCommandSide_ImportHuman(t *testing.T) {
|
||||
uniqueConstraintsFromEventConstraint(user.NewAddUsernameUniqueConstraint("username", "org1", true)),
|
||||
),
|
||||
),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1", "code1"),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
userPasswordAlg: crypto.CreateMockHashAlg(gomock.NewController(t)),
|
||||
passwordlessInitCode: GetMockSecretGenerator(t),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1", "code1"),
|
||||
userPasswordAlg: crypto.CreateMockHashAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
@ -1152,7 +1148,9 @@ func TestCommandSide_ImportHuman(t *testing.T) {
|
||||
IsEmailVerified: true,
|
||||
},
|
||||
},
|
||||
passwordless: true,
|
||||
passwordless: true,
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
passwordlessInitCode: GetMockSecretGenerator(t),
|
||||
},
|
||||
res: res{
|
||||
wantHuman: &domain.Human{
|
||||
@ -1242,7 +1240,6 @@ func TestCommandSide_ImportHuman(t *testing.T) {
|
||||
),
|
||||
),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
userPasswordAlg: crypto.CreateMockHashAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
@ -1265,6 +1262,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
|
||||
PhoneNumber: "+41711234567",
|
||||
},
|
||||
},
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
res: res{
|
||||
wantHuman: &domain.Human{
|
||||
@ -1340,7 +1338,6 @@ func TestCommandSide_ImportHuman(t *testing.T) {
|
||||
),
|
||||
),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
userPasswordAlg: crypto.CreateMockHashAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
@ -1364,6 +1361,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
|
||||
IsPhoneVerified: true,
|
||||
},
|
||||
},
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
res: res{
|
||||
wantHuman: &domain.Human{
|
||||
@ -1392,14 +1390,11 @@ func TestCommandSide_ImportHuman(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
idGenerator: tt.fields.idGenerator,
|
||||
initializeUserCode: tt.fields.secretGenerator,
|
||||
phoneVerificationCode: tt.fields.secretGenerator,
|
||||
userPasswordAlg: tt.fields.userPasswordAlg,
|
||||
passwordlessInitCode: tt.fields.passwordlessInitCode,
|
||||
eventstore: tt.fields.eventstore,
|
||||
idGenerator: tt.fields.idGenerator,
|
||||
userPasswordAlg: tt.fields.userPasswordAlg,
|
||||
}
|
||||
gotHuman, gotCode, err := r.ImportHuman(tt.args.ctx, tt.args.orgID, tt.args.human, tt.args.passwordless)
|
||||
gotHuman, gotCode, err := r.ImportHuman(tt.args.ctx, tt.args.orgID, tt.args.human, tt.args.passwordless, tt.args.secretGenerator, tt.args.secretGenerator, tt.args.secretGenerator)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
@ -1418,15 +1413,15 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
idGenerator id.Generator
|
||||
secretGenerator crypto.Generator
|
||||
userPasswordAlg crypto.HashAlgorithm
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
orgID string
|
||||
human *domain.Human
|
||||
link *domain.UserIDPLink
|
||||
orgMemberRoles []string
|
||||
ctx context.Context
|
||||
orgID string
|
||||
human *domain.Human
|
||||
link *domain.UserIDPLink
|
||||
orgMemberRoles []string
|
||||
secretGenerator crypto.Generator
|
||||
}
|
||||
type res struct {
|
||||
want *domain.Human
|
||||
@ -1858,7 +1853,6 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
|
||||
),
|
||||
),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
userPasswordAlg: crypto.CreateMockHashAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
@ -1876,6 +1870,7 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
|
||||
EmailAddress: "email@test.ch",
|
||||
},
|
||||
},
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
res: res{
|
||||
want: &domain.Human{
|
||||
@ -1957,7 +1952,6 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
|
||||
),
|
||||
),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
userPasswordAlg: crypto.CreateMockHashAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
@ -1976,6 +1970,7 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
|
||||
EmailAddress: "email@test.ch",
|
||||
},
|
||||
},
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
res: res{
|
||||
want: &domain.Human{
|
||||
@ -2049,7 +2044,6 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
|
||||
),
|
||||
),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
userPasswordAlg: crypto.CreateMockHashAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
@ -2069,6 +2063,7 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
|
||||
IsEmailVerified: true,
|
||||
},
|
||||
},
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
res: res{
|
||||
want: &domain.Human{
|
||||
@ -2161,7 +2156,6 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
|
||||
),
|
||||
),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
userPasswordAlg: crypto.CreateMockHashAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
@ -2183,6 +2177,7 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
|
||||
SecretString: "password",
|
||||
},
|
||||
},
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
res: res{
|
||||
want: &domain.Human{
|
||||
@ -2271,7 +2266,6 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
|
||||
),
|
||||
),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
userPasswordAlg: crypto.CreateMockHashAlg(gomock.NewController(t)),
|
||||
},
|
||||
args: args{
|
||||
@ -2294,6 +2288,7 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
|
||||
SecretString: "password",
|
||||
},
|
||||
},
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
},
|
||||
res: res{
|
||||
want: &domain.Human{
|
||||
@ -2322,13 +2317,11 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
idGenerator: tt.fields.idGenerator,
|
||||
initializeUserCode: tt.fields.secretGenerator,
|
||||
phoneVerificationCode: tt.fields.secretGenerator,
|
||||
userPasswordAlg: tt.fields.userPasswordAlg,
|
||||
eventstore: tt.fields.eventstore,
|
||||
idGenerator: tt.fields.idGenerator,
|
||||
userPasswordAlg: tt.fields.userPasswordAlg,
|
||||
}
|
||||
got, err := r.RegisterHuman(tt.args.ctx, tt.args.orgID, tt.args.human, tt.args.link, tt.args.orgMemberRoles)
|
||||
got, err := r.RegisterHuman(tt.args.ctx, tt.args.orgID, tt.args.human, tt.args.link, tt.args.orgMemberRoles, tt.args.secretGenerator, tt.args.secretGenerator)
|
||||
if tt.res.err == nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
@ -129,8 +129,8 @@ func (c *Commands) HumanAddPasswordlessSetup(ctx context.Context, userID, resour
|
||||
return createdWebAuthN, nil
|
||||
}
|
||||
|
||||
func (c *Commands) HumanAddPasswordlessSetupInitCode(ctx context.Context, userID, resourceowner, codeID, verificationCode string, preferredPlatformType domain.AuthenticatorAttachment) (*domain.WebAuthNToken, error) {
|
||||
err := c.humanVerifyPasswordlessInitCode(ctx, userID, resourceowner, codeID, verificationCode)
|
||||
func (c *Commands) HumanAddPasswordlessSetupInitCode(ctx context.Context, userID, resourceowner, codeID, verificationCode string, preferredPlatformType domain.AuthenticatorAttachment, passwordlessCodeGenerator crypto.Generator) (*domain.WebAuthNToken, error) {
|
||||
err := c.humanVerifyPasswordlessInitCode(ctx, userID, resourceowner, codeID, verificationCode, passwordlessCodeGenerator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -208,8 +208,8 @@ func (c *Commands) HumanVerifyU2FSetup(ctx context.Context, userID, resourceowne
|
||||
return writeModelToObjectDetails(&verifyWebAuthN.WriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) HumanPasswordlessSetupInitCode(ctx context.Context, userID, resourceowner, tokenName, userAgentID, codeID, verificationCode string, credentialData []byte) (*domain.ObjectDetails, error) {
|
||||
err := c.humanVerifyPasswordlessInitCode(ctx, userID, resourceowner, codeID, verificationCode)
|
||||
func (c *Commands) HumanPasswordlessSetupInitCode(ctx context.Context, userID, resourceowner, tokenName, userAgentID, codeID, verificationCode string, credentialData []byte, passwordlessCodeGenerator crypto.Generator) (*domain.ObjectDetails, error) {
|
||||
err := c.humanVerifyPasswordlessInitCode(ctx, userID, resourceowner, codeID, verificationCode, passwordlessCodeGenerator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -483,8 +483,8 @@ func (c *Commands) HumanRemovePasswordless(ctx context.Context, userID, webAuthN
|
||||
return c.removeHumanWebAuthN(ctx, userID, webAuthNID, resourceOwner, event)
|
||||
}
|
||||
|
||||
func (c *Commands) HumanAddPasswordlessInitCode(ctx context.Context, userID, resourceOwner string) (*domain.PasswordlessInitCode, error) {
|
||||
codeEvent, initCode, code, err := c.humanAddPasswordlessInitCode(ctx, userID, resourceOwner, true)
|
||||
func (c *Commands) HumanAddPasswordlessInitCode(ctx context.Context, userID, resourceOwner string, passwordlessCodeGenerator crypto.Generator) (*domain.PasswordlessInitCode, error) {
|
||||
codeEvent, initCode, code, err := c.humanAddPasswordlessInitCode(ctx, userID, resourceOwner, true, passwordlessCodeGenerator)
|
||||
pushedEvents, err := c.eventstore.Push(ctx, codeEvent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -496,8 +496,8 @@ func (c *Commands) HumanAddPasswordlessInitCode(ctx context.Context, userID, res
|
||||
return writeModelToPasswordlessInitCode(initCode, code), nil
|
||||
}
|
||||
|
||||
func (c *Commands) HumanSendPasswordlessInitCode(ctx context.Context, userID, resourceOwner string) (*domain.PasswordlessInitCode, error) {
|
||||
codeEvent, initCode, code, err := c.humanAddPasswordlessInitCode(ctx, userID, resourceOwner, false)
|
||||
func (c *Commands) HumanSendPasswordlessInitCode(ctx context.Context, userID, resourceOwner string, passwordlessCodeGenerator crypto.Generator) (*domain.PasswordlessInitCode, error) {
|
||||
codeEvent, initCode, code, err := c.humanAddPasswordlessInitCode(ctx, userID, resourceOwner, false, passwordlessCodeGenerator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -512,7 +512,7 @@ func (c *Commands) HumanSendPasswordlessInitCode(ctx context.Context, userID, re
|
||||
return writeModelToPasswordlessInitCode(initCode, code), nil
|
||||
}
|
||||
|
||||
func (c *Commands) humanAddPasswordlessInitCode(ctx context.Context, userID, resourceOwner string, direct bool) (eventstore.Command, *HumanPasswordlessInitCodeWriteModel, string, error) {
|
||||
func (c *Commands) humanAddPasswordlessInitCode(ctx context.Context, userID, resourceOwner string, direct bool, passwordlessCodeGenerator crypto.Generator) (eventstore.Command, *HumanPasswordlessInitCodeWriteModel, string, error) {
|
||||
if userID == "" {
|
||||
return nil, nil, "", caos_errs.ThrowPreconditionFailed(nil, "COMMAND-GVfg3", "Errors.IDMissing")
|
||||
}
|
||||
@ -527,7 +527,7 @@ func (c *Commands) humanAddPasswordlessInitCode(ctx context.Context, userID, res
|
||||
return nil, nil, "", err
|
||||
}
|
||||
|
||||
cryptoCode, code, err := crypto.NewCode(c.passwordlessInitCode)
|
||||
cryptoCode, code, err := crypto.NewCode(passwordlessCodeGenerator)
|
||||
if err != nil {
|
||||
return nil, nil, "", err
|
||||
}
|
||||
@ -539,7 +539,7 @@ func (c *Commands) humanAddPasswordlessInitCode(ctx context.Context, userID, res
|
||||
return usr_repo.NewHumanPasswordlessInitCodeRequestedEvent(ctx, agg, id, cryptoCode, exp)
|
||||
}
|
||||
}
|
||||
codeEvent := codeEventCreator(ctx, UserAggregateFromWriteModel(&initCode.WriteModel), codeID, cryptoCode, c.passwordlessInitCode.Expiry())
|
||||
codeEvent := codeEventCreator(ctx, UserAggregateFromWriteModel(&initCode.WriteModel), codeID, cryptoCode, passwordlessCodeGenerator.Expiry())
|
||||
return codeEvent, initCode, code, nil
|
||||
}
|
||||
|
||||
@ -563,7 +563,7 @@ func (c *Commands) HumanPasswordlessInitCodeSent(ctx context.Context, userID, re
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Commands) humanVerifyPasswordlessInitCode(ctx context.Context, userID, resourceOwner, codeID, verificationCode string) error {
|
||||
func (c *Commands) humanVerifyPasswordlessInitCode(ctx context.Context, userID, resourceOwner, codeID, verificationCode string, passwordlessCodeGenerator crypto.Generator) error {
|
||||
if userID == "" || codeID == "" {
|
||||
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-GVfg3", "Errors.IDMissing")
|
||||
}
|
||||
@ -572,7 +572,7 @@ func (c *Commands) humanVerifyPasswordlessInitCode(ctx context.Context, userID,
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = crypto.VerifyCode(initCode.ChangeDate, initCode.Expiration, initCode.CryptoCode, verificationCode, c.passwordlessInitCode)
|
||||
err = crypto.VerifyCode(initCode.ChangeDate, initCode.Expiration, initCode.CryptoCode, verificationCode, passwordlessCodeGenerator)
|
||||
if err != nil || initCode.State != domain.PasswordlessInitCodeStateActive {
|
||||
userAgg := UserAggregateFromWriteModel(&initCode.WriteModel)
|
||||
_, err = c.eventstore.Push(ctx, usr_repo.NewHumanPasswordlessInitCodeCheckFailedEvent(ctx, userAgg, codeID))
|
||||
|
@ -9,24 +9,23 @@ import (
|
||||
"github.com/caos/zitadel/internal/notification/channels/chat"
|
||||
"github.com/caos/zitadel/internal/notification/channels/fs"
|
||||
"github.com/caos/zitadel/internal/notification/channels/log"
|
||||
"github.com/caos/zitadel/internal/notification/channels/smtp"
|
||||
"github.com/caos/zitadel/internal/notification/channels/twilio"
|
||||
"github.com/caos/zitadel/internal/notification/templates"
|
||||
)
|
||||
|
||||
type SystemDefaults struct {
|
||||
DefaultLanguage language.Tag
|
||||
Domain string
|
||||
ZitadelDocs ZitadelDocs
|
||||
SecretGenerators SecretGenerators
|
||||
UserVerificationKey *crypto.KeyConfig
|
||||
IDPConfigVerificationKey *crypto.KeyConfig
|
||||
Multifactors MultifactorConfig
|
||||
VerificationLifetimes VerificationLifetimes
|
||||
DomainVerification DomainVerification
|
||||
IamID string
|
||||
Notifications Notifications
|
||||
KeyConfig KeyConfig
|
||||
DefaultLanguage language.Tag
|
||||
Domain string
|
||||
ZitadelDocs ZitadelDocs
|
||||
SecretGenerators SecretGenerators
|
||||
UserVerificationKey *crypto.KeyConfig
|
||||
IDPConfigVerificationKey *crypto.KeyConfig
|
||||
SMTPPasswordVerificationKey *crypto.KeyConfig
|
||||
Multifactors MultifactorConfig
|
||||
VerificationLifetimes VerificationLifetimes
|
||||
DomainVerification DomainVerification
|
||||
Notifications Notifications
|
||||
KeyConfig KeyConfig
|
||||
}
|
||||
|
||||
type ZitadelDocs struct {
|
||||
@ -35,15 +34,9 @@ type ZitadelDocs struct {
|
||||
}
|
||||
|
||||
type SecretGenerators struct {
|
||||
PasswordSaltCost int
|
||||
ClientSecretGenerator crypto.GeneratorConfig
|
||||
InitializeUserCode crypto.GeneratorConfig
|
||||
EmailVerificationCode crypto.GeneratorConfig
|
||||
PhoneVerificationCode crypto.GeneratorConfig
|
||||
PasswordVerificationCode crypto.GeneratorConfig
|
||||
PasswordlessInitCode crypto.GeneratorConfig
|
||||
MachineKeySize uint32
|
||||
ApplicationKeySize uint32
|
||||
PasswordSaltCost int
|
||||
MachineKeySize uint32
|
||||
ApplicationKeySize uint32
|
||||
}
|
||||
|
||||
type MultifactorConfig struct {
|
||||
@ -69,10 +62,9 @@ type DomainVerification struct {
|
||||
}
|
||||
|
||||
type Notifications struct {
|
||||
DebugMode bool
|
||||
Endpoints Endpoints
|
||||
Providers Channels
|
||||
TemplateData TemplateData
|
||||
DebugMode bool
|
||||
Endpoints Endpoints
|
||||
Providers Channels
|
||||
}
|
||||
|
||||
type Endpoints struct {
|
||||
@ -85,7 +77,6 @@ type Endpoints struct {
|
||||
|
||||
type Channels struct {
|
||||
Chat chat.ChatConfig
|
||||
Email smtp.EmailConfig
|
||||
Twilio twilio.TwilioConfig
|
||||
FileSystem fs.FSConfig
|
||||
Log log.LogConfig
|
||||
|
23
internal/domain/secret_generator.go
Normal file
23
internal/domain/secret_generator.go
Normal file
@ -0,0 +1,23 @@
|
||||
package domain
|
||||
|
||||
type SecretGeneratorType int32
|
||||
|
||||
const (
|
||||
SecretGeneratorTypeUnspecified SecretGeneratorType = iota
|
||||
SecretGeneratorTypeInitCode
|
||||
SecretGeneratorTypeVerifyEmailCode
|
||||
SecretGeneratorTypeVerifyPhoneCode
|
||||
SecretGeneratorTypePasswordResetCode
|
||||
SecretGeneratorTypePasswordlessInitCode
|
||||
SecretGeneratorTypeAppSecret
|
||||
|
||||
secretGeneratorTypeCount
|
||||
)
|
||||
|
||||
type SecretGeneratorState int32
|
||||
|
||||
const (
|
||||
SecretGeneratorStateUnspecified SecretGeneratorState = iota
|
||||
SecretGeneratorStateActive
|
||||
SecretGeneratorStateRemoved
|
||||
)
|
8
internal/domain/smtp.go
Normal file
8
internal/domain/smtp.go
Normal file
@ -0,0 +1,8 @@
|
||||
package domain
|
||||
|
||||
type SMTPConfigState int32
|
||||
|
||||
const (
|
||||
SMTPConfigStateUnspecified SMTPConfigState = iota
|
||||
SMTPConfigStateActive
|
||||
)
|
@ -1,26 +1,30 @@
|
||||
package smtp
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"net"
|
||||
"net/smtp"
|
||||
|
||||
"github.com/caos/zitadel/internal/notification/messages"
|
||||
|
||||
"github.com/caos/logging"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/notification/channels"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/caos/zitadel/internal/notification/messages"
|
||||
)
|
||||
|
||||
var _ channels.NotificationChannel = (*Email)(nil)
|
||||
|
||||
type Email struct {
|
||||
smtpClient *smtp.Client
|
||||
smtpClient *smtp.Client
|
||||
senderAddress string
|
||||
senderName string
|
||||
}
|
||||
|
||||
func InitSMTPChannel(config EmailConfig) (*Email, error) {
|
||||
client, err := config.SMTP.connectToSMTP(config.Tls)
|
||||
func InitSMTPChannel(ctx context.Context, getSMTPConfig func(ctx context.Context) (*EmailConfig, error)) (*Email, error) {
|
||||
smtpConfig, err := getSMTPConfig(ctx)
|
||||
client, err := smtpConfig.SMTP.connectToSMTP(smtpConfig.Tls)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -42,12 +46,12 @@ func (email *Email) HandleMessage(message channels.Message) error {
|
||||
if emailMsg.Content == "" || emailMsg.Subject == "" || len(emailMsg.Recipients) == 0 {
|
||||
return caos_errs.ThrowInternalf(nil, "EMAIL-zGemZ", "subject, recipients and content must be set but got subject %s, recipients length %d and content length %d", emailMsg.Subject, len(emailMsg.Recipients), len(emailMsg.Content))
|
||||
}
|
||||
|
||||
emailMsg.SenderEmail = email.senderAddress
|
||||
emailMsg.SenderName = email.senderName
|
||||
// To && From
|
||||
if err := email.smtpClient.Mail(emailMsg.SenderEmail); err != nil {
|
||||
return caos_errs.ThrowInternalf(err, "EMAIL-s3is3", "could not set sender: %v", emailMsg.SenderEmail)
|
||||
}
|
||||
|
||||
for _, recp := range append(append(emailMsg.Recipients, emailMsg.CC...), emailMsg.BCC...) {
|
||||
if err := email.smtpClient.Rcpt(recp); err != nil {
|
||||
return caos_errs.ThrowInternalf(err, "EMAIL-s4is4", "could not set recipient: %v", recp)
|
||||
|
@ -20,13 +20,18 @@ type Email struct {
|
||||
BCC []string
|
||||
CC []string
|
||||
SenderEmail string
|
||||
SenderName string
|
||||
Subject string
|
||||
Content string
|
||||
}
|
||||
|
||||
func (msg *Email) GetContent() string {
|
||||
headers := make(map[string]string)
|
||||
headers["From"] = msg.SenderEmail
|
||||
from := msg.SenderEmail
|
||||
if msg.SenderName != "" {
|
||||
from = fmt.Sprintf("%s <%s>", msg.SenderName, msg.SenderEmail)
|
||||
}
|
||||
headers["From"] = from
|
||||
headers["To"] = strings.Join(msg.Recipients, ", ")
|
||||
headers["Cc"] = strings.Join(msg.CC, ", ")
|
||||
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"database/sql"
|
||||
|
||||
"github.com/caos/logging"
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/rakyll/statik/fs"
|
||||
|
||||
"github.com/caos/zitadel/internal/command"
|
||||
@ -17,10 +18,10 @@ type Config struct {
|
||||
Repository eventsourcing.Config
|
||||
}
|
||||
|
||||
func Start(config Config, systemDefaults sd.SystemDefaults, command *command.Commands, queries *query.Queries, dbClient *sql.DB, assetsPrefix string) {
|
||||
func Start(config Config, systemDefaults sd.SystemDefaults, command *command.Commands, queries *query.Queries, dbClient *sql.DB, assetsPrefix string, smtpPasswordEncAlg crypto.EncryptionAlgorithm) {
|
||||
statikFS, err := fs.NewWithNamespace("notification")
|
||||
logging.OnError(err).Panic("unable to start listener")
|
||||
|
||||
_, err = eventsourcing.Start(config.Repository, statikFS, systemDefaults, command, queries, dbClient, assetsPrefix)
|
||||
_, err = eventsourcing.Start(config.Repository, statikFS, systemDefaults, command, queries, dbClient, assetsPrefix, smtpPasswordEncAlg)
|
||||
logging.OnError(err).Panic("unable to start app")
|
||||
}
|
||||
|
@ -34,14 +34,13 @@ func (h *handler) Eventstore() v1.Eventstore {
|
||||
return h.es
|
||||
}
|
||||
|
||||
func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es v1.Eventstore, command *command.Commands, queries *query.Queries, systemDefaults sd.SystemDefaults, dir http.FileSystem, assetsPrefix string) []queryv1.Handler {
|
||||
func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es v1.Eventstore, command *command.Commands, queries *query.Queries, systemDefaults sd.SystemDefaults, dir http.FileSystem, assetsPrefix string, smtpPasswordEncAlg crypto.EncryptionAlgorithm) []queryv1.Handler {
|
||||
aesCrypto, err := crypto.NewAESCrypto(systemDefaults.UserVerificationKey)
|
||||
logging.OnError(err).Fatal("error create new aes crypto")
|
||||
|
||||
return []queryv1.Handler{
|
||||
newNotifyUser(
|
||||
handler{view, bulkLimit, configs.cycleDuration("User"), errorCount, es},
|
||||
systemDefaults.IamID,
|
||||
queries,
|
||||
),
|
||||
newNotification(
|
||||
@ -52,6 +51,7 @@ func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es
|
||||
aesCrypto,
|
||||
dir,
|
||||
assetsPrefix,
|
||||
smtpPasswordEncAlg,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import (
|
||||
queryv1 "github.com/caos/zitadel/internal/eventstore/v1/query"
|
||||
"github.com/caos/zitadel/internal/eventstore/v1/spooler"
|
||||
"github.com/caos/zitadel/internal/i18n"
|
||||
"github.com/caos/zitadel/internal/notification/channels/smtp"
|
||||
"github.com/caos/zitadel/internal/notification/types"
|
||||
"github.com/caos/zitadel/internal/query"
|
||||
user_repo "github.com/caos/zitadel/internal/repository/user"
|
||||
@ -34,13 +35,14 @@ const (
|
||||
|
||||
type Notification struct {
|
||||
handler
|
||||
command *command.Commands
|
||||
systemDefaults sd.SystemDefaults
|
||||
AesCrypto crypto.EncryptionAlgorithm
|
||||
statikDir http.FileSystem
|
||||
subscription *v1.Subscription
|
||||
assetsPrefix string
|
||||
queries *query.Queries
|
||||
command *command.Commands
|
||||
systemDefaults sd.SystemDefaults
|
||||
AesCrypto crypto.EncryptionAlgorithm
|
||||
statikDir http.FileSystem
|
||||
subscription *v1.Subscription
|
||||
assetsPrefix string
|
||||
queries *query.Queries
|
||||
smtpPasswordCrypto crypto.EncryptionAlgorithm
|
||||
}
|
||||
|
||||
func newNotification(
|
||||
@ -51,15 +53,17 @@ func newNotification(
|
||||
aesCrypto crypto.EncryptionAlgorithm,
|
||||
statikDir http.FileSystem,
|
||||
assetsPrefix string,
|
||||
smtpPasswordEncAlg crypto.EncryptionAlgorithm,
|
||||
) *Notification {
|
||||
h := &Notification{
|
||||
handler: handler,
|
||||
command: command,
|
||||
systemDefaults: defaults,
|
||||
statikDir: statikDir,
|
||||
AesCrypto: aesCrypto,
|
||||
assetsPrefix: assetsPrefix,
|
||||
queries: query,
|
||||
handler: handler,
|
||||
command: command,
|
||||
systemDefaults: defaults,
|
||||
statikDir: statikDir,
|
||||
AesCrypto: aesCrypto,
|
||||
assetsPrefix: assetsPrefix,
|
||||
queries: query,
|
||||
smtpPasswordCrypto: smtpPasswordEncAlg,
|
||||
}
|
||||
|
||||
h.subscribe()
|
||||
@ -161,7 +165,7 @@ func (n *Notification) handleInitUserCode(event *models.Event) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
err = types.SendUserInitCode(string(template.Template), translator, user, initCode, n.systemDefaults, n.AesCrypto, colors, n.assetsPrefix)
|
||||
err = types.SendUserInitCode(ctx, string(template.Template), translator, user, initCode, n.systemDefaults, n.getSMTPConfig, n.AesCrypto, colors, n.assetsPrefix)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -199,7 +203,7 @@ func (n *Notification) handlePasswordCode(event *models.Event) (err error) {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = types.SendPasswordCode(string(template.Template), translator, user, pwCode, n.systemDefaults, n.AesCrypto, colors, n.assetsPrefix)
|
||||
err = types.SendPasswordCode(ctx, string(template.Template), translator, user, pwCode, n.systemDefaults, n.getSMTPConfig, n.AesCrypto, colors, n.assetsPrefix)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -238,7 +242,7 @@ func (n *Notification) handleEmailVerificationCode(event *models.Event) (err err
|
||||
return err
|
||||
}
|
||||
|
||||
err = types.SendEmailVerificationCode(string(template.Template), translator, user, emailCode, n.systemDefaults, n.AesCrypto, colors, n.assetsPrefix)
|
||||
err = types.SendEmailVerificationCode(ctx, string(template.Template), translator, user, emailCode, n.systemDefaults, n.getSMTPConfig, n.AesCrypto, colors, n.assetsPrefix)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -303,7 +307,8 @@ func (n *Notification) handleDomainClaimed(event *models.Event) (err error) {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = types.SendDomainClaimed(string(template.Template), translator, user, data["userName"], n.systemDefaults, colors, n.assetsPrefix)
|
||||
|
||||
err = types.SendDomainClaimed(ctx, string(template.Template), translator, user, data["userName"], n.systemDefaults, n.getSMTPConfig, colors, n.assetsPrefix)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -349,7 +354,8 @@ func (n *Notification) handlePasswordlessRegistrationLink(event *models.Event) (
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = types.SendPasswordlessRegistrationLink(string(template.Template), translator, user, addedEvent, n.systemDefaults, n.AesCrypto, colors, n.assetsPrefix)
|
||||
|
||||
err = types.SendPasswordlessRegistrationLink(ctx, string(template.Template), translator, user, addedEvent, n.systemDefaults, n.getSMTPConfig, n.AesCrypto, colors, n.assetsPrefix)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -410,12 +416,34 @@ func (n *Notification) getMailTemplate(ctx context.Context) (*query.MailTemplate
|
||||
return n.queries.MailTemplateByOrg(ctx, authz.GetCtxData(ctx).OrgID)
|
||||
}
|
||||
|
||||
func (n *Notification) getTranslatorWithOrgTexts(orgID, textType string) (*i18n.Translator, error) {
|
||||
translator, err := i18n.NewTranslator(n.statikDir, i18n.TranslatorConfig{DefaultLanguage: n.systemDefaults.DefaultLanguage})
|
||||
// Read iam smtp config
|
||||
func (n *Notification) getSMTPConfig(ctx context.Context) (*smtp.EmailConfig, error) {
|
||||
config, err := n.queries.SMTPConfigByAggregateID(ctx, domain.IAMID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ctx := context.TODO()
|
||||
password, err := crypto.Decrypt(config.Password, n.smtpPasswordCrypto)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &smtp.EmailConfig{
|
||||
From: config.SenderAddress,
|
||||
FromName: config.SenderName,
|
||||
SMTP: smtp.SMTP{
|
||||
Host: config.Host,
|
||||
User: config.User,
|
||||
Password: string(password),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (n *Notification) getTranslatorWithOrgTexts(orgID, textType string) (*i18n.Translator, error) {
|
||||
ctx := context.Background()
|
||||
translator, err := i18n.NewTranslator(n.statikDir, i18n.TranslatorConfig{DefaultLanguage: n.queries.GetDefaultLanguage(ctx)})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
allCustomTexts, err := n.queries.CustomTextListByTemplate(ctx, domain.IAMID, textType)
|
||||
if err != nil {
|
||||
return translator, nil
|
||||
|
@ -26,19 +26,16 @@ const (
|
||||
|
||||
type NotifyUser struct {
|
||||
handler
|
||||
iamID string
|
||||
subscription *v1.Subscription
|
||||
queries *query2.Queries
|
||||
}
|
||||
|
||||
func newNotifyUser(
|
||||
handler handler,
|
||||
iamID string,
|
||||
queries *query2.Queries,
|
||||
) *NotifyUser {
|
||||
h := &NotifyUser{
|
||||
handler: handler,
|
||||
iamID: iamID,
|
||||
queries: queries,
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
|
||||
"github.com/caos/zitadel/internal/command"
|
||||
sd "github.com/caos/zitadel/internal/config/systemdefaults"
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
v1 "github.com/caos/zitadel/internal/eventstore/v1"
|
||||
es_spol "github.com/caos/zitadel/internal/eventstore/v1/spooler"
|
||||
"github.com/caos/zitadel/internal/notification/repository/eventsourcing/spooler"
|
||||
@ -21,7 +22,7 @@ type EsRepository struct {
|
||||
spooler *es_spol.Spooler
|
||||
}
|
||||
|
||||
func Start(conf Config, dir http.FileSystem, systemDefaults sd.SystemDefaults, command *command.Commands, queries *query.Queries, dbClient *sql.DB, assetsPrefix string) (*EsRepository, error) {
|
||||
func Start(conf Config, dir http.FileSystem, systemDefaults sd.SystemDefaults, command *command.Commands, queries *query.Queries, dbClient *sql.DB, assetsPrefix string, smtpPasswordEncAlg crypto.EncryptionAlgorithm) (*EsRepository, error) {
|
||||
es, err := v1.Start(dbClient)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -32,7 +33,7 @@ func Start(conf Config, dir http.FileSystem, systemDefaults sd.SystemDefaults, c
|
||||
return nil, err
|
||||
}
|
||||
|
||||
spool := spooler.StartSpooler(conf.Spooler, es, view, dbClient, command, queries, systemDefaults, dir, assetsPrefix)
|
||||
spool := spooler.StartSpooler(conf.Spooler, es, view, dbClient, command, queries, systemDefaults, dir, assetsPrefix, smtpPasswordEncAlg)
|
||||
|
||||
return &EsRepository{
|
||||
spool,
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
|
||||
"github.com/caos/zitadel/internal/command"
|
||||
sd "github.com/caos/zitadel/internal/config/systemdefaults"
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
v1 "github.com/caos/zitadel/internal/eventstore/v1"
|
||||
"github.com/caos/zitadel/internal/eventstore/v1/spooler"
|
||||
"github.com/caos/zitadel/internal/notification/repository/eventsourcing/handler"
|
||||
@ -20,12 +21,12 @@ type SpoolerConfig struct {
|
||||
Handlers handler.Configs
|
||||
}
|
||||
|
||||
func StartSpooler(c SpoolerConfig, es v1.Eventstore, view *view.View, sql *sql.DB, command *command.Commands, queries *query.Queries, systemDefaults sd.SystemDefaults, dir http.FileSystem, assetsPrefix string) *spooler.Spooler {
|
||||
func StartSpooler(c SpoolerConfig, es v1.Eventstore, view *view.View, sql *sql.DB, command *command.Commands, queries *query.Queries, systemDefaults sd.SystemDefaults, dir http.FileSystem, assetsPrefix string, smtpPasswordEncAlg crypto.EncryptionAlgorithm) *spooler.Spooler {
|
||||
spoolerConfig := spooler.Config{
|
||||
Eventstore: es,
|
||||
Locker: &locker{dbClient: sql},
|
||||
ConcurrentWorkers: c.ConcurrentWorkers,
|
||||
ViewHandlers: handler.Register(c.Handlers, c.BulkLimit, c.FailureCountUntilSkip, view, es, command, queries, systemDefaults, dir, assetsPrefix),
|
||||
ViewHandlers: handler.Register(c.Handlers, c.BulkLimit, c.FailureCountUntilSkip, view, es, command, queries, systemDefaults, dir, assetsPrefix, smtpPasswordEncAlg),
|
||||
}
|
||||
spool := spoolerConfig.New()
|
||||
spool.Start()
|
||||
|
@ -1,12 +1,14 @@
|
||||
package senders
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/config/systemdefaults"
|
||||
"github.com/caos/zitadel/internal/notification/channels"
|
||||
"github.com/caos/zitadel/internal/notification/channels/smtp"
|
||||
)
|
||||
|
||||
func EmailChannels(config systemdefaults.Notifications) (channels.NotificationChannel, error) {
|
||||
func EmailChannels(ctx context.Context, config systemdefaults.Notifications, emailConfig func(ctx context.Context) (*smtp.EmailConfig, error)) (channels.NotificationChannel, error) {
|
||||
|
||||
debug, err := debugChannels(config)
|
||||
if err != nil {
|
||||
@ -14,7 +16,7 @@ func EmailChannels(config systemdefaults.Notifications) (channels.NotificationCh
|
||||
}
|
||||
|
||||
if !config.DebugMode {
|
||||
p, err := smtp.InitSMTPChannel(config.Providers.Email)
|
||||
p, err := smtp.InitSMTPChannel(ctx, emailConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -1,11 +1,13 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/caos/zitadel/internal/config/systemdefaults"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"github.com/caos/zitadel/internal/i18n"
|
||||
"github.com/caos/zitadel/internal/notification/channels/smtp"
|
||||
"github.com/caos/zitadel/internal/notification/templates"
|
||||
"github.com/caos/zitadel/internal/query"
|
||||
view_model "github.com/caos/zitadel/internal/user/repository/view/model"
|
||||
@ -16,7 +18,7 @@ type DomainClaimedData struct {
|
||||
URL string
|
||||
}
|
||||
|
||||
func SendDomainClaimed(mailhtml string, translator *i18n.Translator, user *view_model.NotifyUser, username string, systemDefaults systemdefaults.SystemDefaults, colors *query.LabelPolicy, assetsPrefix string) error {
|
||||
func SendDomainClaimed(ctx context.Context, mailhtml string, translator *i18n.Translator, user *view_model.NotifyUser, username string, systemDefaults systemdefaults.SystemDefaults, emailConfig func(ctx context.Context) (*smtp.EmailConfig, error), colors *query.LabelPolicy, assetsPrefix string) error {
|
||||
url, err := templates.ParseTemplateText(systemDefaults.Notifications.Endpoints.DomainClaimed, &UrlData{UserID: user.ID})
|
||||
if err != nil {
|
||||
return err
|
||||
@ -33,5 +35,5 @@ func SendDomainClaimed(mailhtml string, translator *i18n.Translator, user *view_
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return generateEmail(user, domainClaimedData.Subject, template, systemDefaults.Notifications, true)
|
||||
return generateEmail(ctx, user, domainClaimedData.Subject, template, systemDefaults.Notifications, emailConfig, true)
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/config/systemdefaults"
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"github.com/caos/zitadel/internal/i18n"
|
||||
"github.com/caos/zitadel/internal/notification/channels/smtp"
|
||||
"github.com/caos/zitadel/internal/notification/templates"
|
||||
"github.com/caos/zitadel/internal/query"
|
||||
es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
|
||||
@ -16,7 +19,7 @@ type EmailVerificationCodeData struct {
|
||||
URL string
|
||||
}
|
||||
|
||||
func SendEmailVerificationCode(mailhtml string, translator *i18n.Translator, user *view_model.NotifyUser, code *es_model.EmailCode, systemDefaults systemdefaults.SystemDefaults, alg crypto.EncryptionAlgorithm, colors *query.LabelPolicy, assetsPrefix string) error {
|
||||
func SendEmailVerificationCode(ctx context.Context, mailhtml string, translator *i18n.Translator, user *view_model.NotifyUser, code *es_model.EmailCode, systemDefaults systemdefaults.SystemDefaults, smtpConfig func(ctx context.Context) (*smtp.EmailConfig, error), alg crypto.EncryptionAlgorithm, colors *query.LabelPolicy, assetsPrefix string) error {
|
||||
codeString, err := crypto.DecryptString(code.Code, alg)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -38,5 +41,5 @@ func SendEmailVerificationCode(mailhtml string, translator *i18n.Translator, use
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return generateEmail(user, emailCodeData.Subject, template, systemDefaults.Notifications, true)
|
||||
return generateEmail(ctx, user, emailCodeData.Subject, template, systemDefaults.Notifications, smtpConfig, true)
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/config/systemdefaults"
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"github.com/caos/zitadel/internal/i18n"
|
||||
"github.com/caos/zitadel/internal/notification/channels/smtp"
|
||||
"github.com/caos/zitadel/internal/notification/templates"
|
||||
"github.com/caos/zitadel/internal/query"
|
||||
es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
|
||||
@ -22,7 +25,7 @@ type UrlData struct {
|
||||
PasswordSet bool
|
||||
}
|
||||
|
||||
func SendUserInitCode(mailhtml string, translator *i18n.Translator, user *view_model.NotifyUser, code *es_model.InitUserCode, systemDefaults systemdefaults.SystemDefaults, alg crypto.EncryptionAlgorithm, colors *query.LabelPolicy, assetsPrefix string) error {
|
||||
func SendUserInitCode(ctx context.Context, mailhtml string, translator *i18n.Translator, user *view_model.NotifyUser, code *es_model.InitUserCode, systemDefaults systemdefaults.SystemDefaults, smtpConfig func(ctx context.Context) (*smtp.EmailConfig, error), alg crypto.EncryptionAlgorithm, colors *query.LabelPolicy, assetsPrefix string) error {
|
||||
codeString, err := crypto.DecryptString(code.Code, alg)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -42,5 +45,5 @@ func SendUserInitCode(mailhtml string, translator *i18n.Translator, user *view_m
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return generateEmail(user, initCodeData.Subject, template, systemDefaults.Notifications, true)
|
||||
return generateEmail(ctx, user, initCodeData.Subject, template, systemDefaults.Notifications, smtpConfig, true)
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/config/systemdefaults"
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"github.com/caos/zitadel/internal/i18n"
|
||||
"github.com/caos/zitadel/internal/notification/channels/smtp"
|
||||
"github.com/caos/zitadel/internal/notification/templates"
|
||||
"github.com/caos/zitadel/internal/query"
|
||||
es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
|
||||
@ -18,7 +21,7 @@ type PasswordCodeData struct {
|
||||
URL string
|
||||
}
|
||||
|
||||
func SendPasswordCode(mailhtml string, translator *i18n.Translator, user *view_model.NotifyUser, code *es_model.PasswordCode, systemDefaults systemdefaults.SystemDefaults, alg crypto.EncryptionAlgorithm, colors *query.LabelPolicy, assetsPrefix string) error {
|
||||
func SendPasswordCode(ctx context.Context, mailhtml string, translator *i18n.Translator, user *view_model.NotifyUser, code *es_model.PasswordCode, systemDefaults systemdefaults.SystemDefaults, smtpConfig func(ctx context.Context) (*smtp.EmailConfig, error), alg crypto.EncryptionAlgorithm, colors *query.LabelPolicy, assetsPrefix string) error {
|
||||
codeString, err := crypto.DecryptString(code.Code, alg)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -43,6 +46,6 @@ func SendPasswordCode(mailhtml string, translator *i18n.Translator, user *view_m
|
||||
if code.NotificationType == int32(domain.NotificationTypeSms) {
|
||||
return generateSms(user, passwordResetData.Text, systemDefaults.Notifications, false)
|
||||
}
|
||||
return generateEmail(user, passwordResetData.Subject, template, systemDefaults.Notifications, true)
|
||||
return generateEmail(ctx, user, passwordResetData.Subject, template, systemDefaults.Notifications, smtpConfig, true)
|
||||
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/zitadel/internal/config/systemdefaults"
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"github.com/caos/zitadel/internal/i18n"
|
||||
"github.com/caos/zitadel/internal/notification/channels/smtp"
|
||||
"github.com/caos/zitadel/internal/notification/templates"
|
||||
"github.com/caos/zitadel/internal/query"
|
||||
"github.com/caos/zitadel/internal/repository/user"
|
||||
@ -16,7 +19,7 @@ type PasswordlessRegistrationLinkData struct {
|
||||
URL string
|
||||
}
|
||||
|
||||
func SendPasswordlessRegistrationLink(mailhtml string, translator *i18n.Translator, user *view_model.NotifyUser, code *user.HumanPasswordlessInitCodeRequestedEvent, systemDefaults systemdefaults.SystemDefaults, alg crypto.EncryptionAlgorithm, colors *query.LabelPolicy, assetsPrefix string) error {
|
||||
func SendPasswordlessRegistrationLink(ctx context.Context, mailhtml string, translator *i18n.Translator, user *view_model.NotifyUser, code *user.HumanPasswordlessInitCodeRequestedEvent, systemDefaults systemdefaults.SystemDefaults, smtpConfig func(ctx context.Context) (*smtp.EmailConfig, error), alg crypto.EncryptionAlgorithm, colors *query.LabelPolicy, assetsPrefix string) error {
|
||||
codeString, err := crypto.DecryptString(code.Code, alg)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -33,5 +36,5 @@ func SendPasswordlessRegistrationLink(mailhtml string, translator *i18n.Translat
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return generateEmail(user, emailCodeData.Subject, template, systemDefaults.Notifications, true)
|
||||
return generateEmail(ctx, user, emailCodeData.Subject, template, systemDefaults.Notifications, smtpConfig, true)
|
||||
}
|
||||
|
@ -1,8 +1,10 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
"html"
|
||||
|
||||
"github.com/caos/zitadel/internal/notification/channels/smtp"
|
||||
"github.com/caos/zitadel/internal/notification/messages"
|
||||
"github.com/caos/zitadel/internal/notification/senders"
|
||||
|
||||
@ -10,19 +12,18 @@ import (
|
||||
view_model "github.com/caos/zitadel/internal/user/repository/view/model"
|
||||
)
|
||||
|
||||
func generateEmail(user *view_model.NotifyUser, subject, content string, config systemdefaults.Notifications, lastEmail bool) error {
|
||||
func generateEmail(ctx context.Context, user *view_model.NotifyUser, subject, content string, config systemdefaults.Notifications, smtpConfig func(ctx context.Context) (*smtp.EmailConfig, error), lastEmail bool) error {
|
||||
content = html.UnescapeString(content)
|
||||
message := &messages.Email{
|
||||
SenderEmail: config.Providers.Email.From,
|
||||
Recipients: []string{user.VerifiedEmail},
|
||||
Subject: subject,
|
||||
Content: content,
|
||||
Recipients: []string{user.VerifiedEmail},
|
||||
Subject: subject,
|
||||
Content: content,
|
||||
}
|
||||
if lastEmail {
|
||||
message.Recipients = []string{user.LastEmail}
|
||||
}
|
||||
|
||||
channels, err := senders.EmailChannels(config)
|
||||
channels, err := senders.EmailChannels(ctx, config, smtpConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -186,7 +186,7 @@ func (q *Queries) readLoginTranslationFile(lang string) ([]byte, error) {
|
||||
if !ok {
|
||||
contents, err = q.readTranslationFile(q.LoginDir, fmt.Sprintf("/i18n/%s.yaml", lang))
|
||||
if errors.IsNotFound(err) {
|
||||
contents, err = q.readTranslationFile(q.LoginDir, fmt.Sprintf("/i18n/%s.yaml", q.DefaultLanguage.String()))
|
||||
contents, err = q.readTranslationFile(q.LoginDir, fmt.Sprintf("/i18n/%s.yaml", q.GetDefaultLanguage(context.Background()).String()))
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/query/projection"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -44,6 +45,10 @@ var (
|
||||
name: projection.IAMColumnSetUpDone,
|
||||
table: iamTable,
|
||||
}
|
||||
IAMColumnDefaultLanguage = Column{
|
||||
name: projection.IAMColumnDefaultLanguage,
|
||||
table: iamTable,
|
||||
}
|
||||
)
|
||||
|
||||
type IAM struct {
|
||||
@ -51,10 +56,11 @@ type IAM struct {
|
||||
ChangeDate time.Time
|
||||
Sequence uint64
|
||||
|
||||
GlobalOrgID string
|
||||
IAMProjectID string
|
||||
SetupStarted domain.Step
|
||||
SetupDone domain.Step
|
||||
GlobalOrgID string
|
||||
IAMProjectID string
|
||||
DefaultLanguage language.Tag
|
||||
SetupStarted domain.Step
|
||||
SetupDone domain.Step
|
||||
}
|
||||
|
||||
type IAMSearchQueries struct {
|
||||
@ -83,6 +89,14 @@ func (q *Queries) IAMByID(ctx context.Context, id string) (*IAM, error) {
|
||||
return scan(row)
|
||||
}
|
||||
|
||||
func (q *Queries) GetDefaultLanguage(ctx context.Context) language.Tag {
|
||||
iam, err := q.IAMByID(ctx, domain.IAMID)
|
||||
if err != nil {
|
||||
return language.Und
|
||||
}
|
||||
return iam.DefaultLanguage
|
||||
}
|
||||
|
||||
func prepareIAMQuery() (sq.SelectBuilder, func(*sql.Row) (*IAM, error)) {
|
||||
return sq.Select(
|
||||
IAMColumnID.identifier(),
|
||||
@ -92,18 +106,21 @@ func prepareIAMQuery() (sq.SelectBuilder, func(*sql.Row) (*IAM, error)) {
|
||||
IAMColumnProjectID.identifier(),
|
||||
IAMColumnSetupStarted.identifier(),
|
||||
IAMColumnSetupDone.identifier(),
|
||||
IAMColumnDefaultLanguage.identifier(),
|
||||
).
|
||||
From(iamTable.identifier()).PlaceholderFormat(sq.Dollar),
|
||||
func(row *sql.Row) (*IAM, error) {
|
||||
o := new(IAM)
|
||||
iam := new(IAM)
|
||||
lang := ""
|
||||
err := row.Scan(
|
||||
&o.ID,
|
||||
&o.ChangeDate,
|
||||
&o.Sequence,
|
||||
&o.GlobalOrgID,
|
||||
&o.IAMProjectID,
|
||||
&o.SetupStarted,
|
||||
&o.SetupDone,
|
||||
&iam.ID,
|
||||
&iam.ChangeDate,
|
||||
&iam.Sequence,
|
||||
&iam.GlobalOrgID,
|
||||
&iam.IAMProjectID,
|
||||
&iam.SetupStarted,
|
||||
&iam.SetupDone,
|
||||
&lang,
|
||||
)
|
||||
if err != nil {
|
||||
if errs.Is(err, sql.ErrNoRows) {
|
||||
@ -111,6 +128,7 @@ func prepareIAMQuery() (sq.SelectBuilder, func(*sql.Row) (*IAM, error)) {
|
||||
}
|
||||
return nil, errors.ThrowInternal(err, "QUERY-d9nw", "Errors.Internal")
|
||||
}
|
||||
return o, nil
|
||||
iam.DefaultLanguage = language.Make(lang)
|
||||
return iam, nil
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
errs "github.com/caos/zitadel/internal/errors"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
func Test_IAMPrepares(t *testing.T) {
|
||||
@ -34,7 +35,8 @@ func Test_IAMPrepares(t *testing.T) {
|
||||
` zitadel.projections.iam.global_org_id,`+
|
||||
` zitadel.projections.iam.iam_project_id,`+
|
||||
` zitadel.projections.iam.setup_started,`+
|
||||
` zitadel.projections.iam.setup_done`+
|
||||
` zitadel.projections.iam.setup_done,`+
|
||||
` zitadel.projections.iam.default_language`+
|
||||
` FROM zitadel.projections.iam`),
|
||||
nil,
|
||||
nil,
|
||||
@ -59,7 +61,8 @@ func Test_IAMPrepares(t *testing.T) {
|
||||
` zitadel.projections.iam.global_org_id,`+
|
||||
` zitadel.projections.iam.iam_project_id,`+
|
||||
` zitadel.projections.iam.setup_started,`+
|
||||
` zitadel.projections.iam.setup_done`+
|
||||
` zitadel.projections.iam.setup_done,`+
|
||||
` zitadel.projections.iam.default_language`+
|
||||
` FROM zitadel.projections.iam`),
|
||||
[]string{
|
||||
"id",
|
||||
@ -69,6 +72,7 @@ func Test_IAMPrepares(t *testing.T) {
|
||||
"iam_project_id",
|
||||
"setup_started",
|
||||
"setup_done",
|
||||
"default_language",
|
||||
},
|
||||
[]driver.Value{
|
||||
"id",
|
||||
@ -78,17 +82,19 @@ func Test_IAMPrepares(t *testing.T) {
|
||||
"project-id",
|
||||
domain.Step2,
|
||||
domain.Step1,
|
||||
"en",
|
||||
},
|
||||
),
|
||||
},
|
||||
object: &IAM{
|
||||
ID: "id",
|
||||
ChangeDate: testNow,
|
||||
Sequence: 20211108,
|
||||
GlobalOrgID: "global-org-id",
|
||||
IAMProjectID: "project-id",
|
||||
SetupStarted: domain.Step2,
|
||||
SetupDone: domain.Step1,
|
||||
ID: "id",
|
||||
ChangeDate: testNow,
|
||||
Sequence: 20211108,
|
||||
GlobalOrgID: "global-org-id",
|
||||
IAMProjectID: "project-id",
|
||||
SetupStarted: domain.Step2,
|
||||
SetupDone: domain.Step1,
|
||||
DefaultLanguage: language.English,
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -102,7 +108,8 @@ func Test_IAMPrepares(t *testing.T) {
|
||||
` zitadel.projections.iam.global_org_id,`+
|
||||
` zitadel.projections.iam.iam_project_id,`+
|
||||
` zitadel.projections.iam.setup_started,`+
|
||||
` zitadel.projections.iam.setup_done`+
|
||||
` zitadel.projections.iam.setup_done,`+
|
||||
` zitadel.projections.iam.default_language`+
|
||||
` FROM zitadel.projections.iam`),
|
||||
sql.ErrConnDone,
|
||||
),
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
|
||||
sq "github.com/Masterminds/squirrel"
|
||||
"github.com/lib/pq"
|
||||
|
||||
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
@ -186,7 +186,7 @@ func (q *Queries) IDPByIDAndResourceOwner(ctx context.Context, id, resourceOwner
|
||||
IDPResourceOwnerCol.identifier(): resourceOwner,
|
||||
},
|
||||
sq.Eq{
|
||||
IDPResourceOwnerCol.identifier(): q.iamID,
|
||||
IDPResourceOwnerCol.identifier(): domain.IAMID,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -47,7 +47,7 @@ func (q *Queries) ActiveLabelPolicyByOrg(ctx context.Context, orgID string) (*La
|
||||
LabelPolicyColID.identifier(): orgID,
|
||||
},
|
||||
sq.Eq{
|
||||
LabelPolicyColID.identifier(): q.iamID,
|
||||
LabelPolicyColID.identifier(): domain.IAMID,
|
||||
},
|
||||
},
|
||||
sq.Eq{
|
||||
@ -73,7 +73,7 @@ func (q *Queries) PreviewLabelPolicyByOrg(ctx context.Context, orgID string) (*L
|
||||
LabelPolicyColID.identifier(): orgID,
|
||||
},
|
||||
sq.Eq{
|
||||
LabelPolicyColID.identifier(): q.iamID,
|
||||
LabelPolicyColID.identifier(): domain.IAMID,
|
||||
},
|
||||
},
|
||||
sq.Eq{
|
||||
@ -93,7 +93,7 @@ func (q *Queries) PreviewLabelPolicyByOrg(ctx context.Context, orgID string) (*L
|
||||
func (q *Queries) DefaultActiveLabelPolicy(ctx context.Context) (*LabelPolicy, error) {
|
||||
stmt, scan := prepareLabelPolicyQuery()
|
||||
query, args, err := stmt.Where(sq.Eq{
|
||||
LabelPolicyColID.identifier(): q.iamID,
|
||||
LabelPolicyColID.identifier(): domain.IAMID,
|
||||
LabelPolicyColState.identifier(): domain.LabelPolicyStateActive,
|
||||
}).
|
||||
OrderBy(LabelPolicyColIsDefault.identifier()).
|
||||
@ -109,7 +109,7 @@ func (q *Queries) DefaultActiveLabelPolicy(ctx context.Context) (*LabelPolicy, e
|
||||
func (q *Queries) DefaultPreviewLabelPolicy(ctx context.Context) (*LabelPolicy, error) {
|
||||
stmt, scan := prepareLabelPolicyQuery()
|
||||
query, args, err := stmt.Where(sq.Eq{
|
||||
LabelPolicyColID.identifier(): q.iamID,
|
||||
LabelPolicyColID.identifier(): domain.IAMID,
|
||||
LabelPolicyColState.identifier(): domain.LabelPolicyStatePreview,
|
||||
}).
|
||||
OrderBy(LabelPolicyColIsDefault.identifier()).
|
||||
|
@ -76,7 +76,7 @@ func (q *Queries) LockoutPolicyByOrg(ctx context.Context, orgID string) (*Lockou
|
||||
LockoutColID.identifier(): orgID,
|
||||
},
|
||||
sq.Eq{
|
||||
LockoutColID.identifier(): q.iamID,
|
||||
LockoutColID.identifier(): domain.IAMID,
|
||||
},
|
||||
}).
|
||||
OrderBy(LockoutColIsDefault.identifier()).
|
||||
@ -92,7 +92,7 @@ func (q *Queries) LockoutPolicyByOrg(ctx context.Context, orgID string) (*Lockou
|
||||
func (q *Queries) DefaultLockoutPolicy(ctx context.Context) (*LockoutPolicy, error) {
|
||||
stmt, scan := prepareLockoutPolicyQuery()
|
||||
query, args, err := stmt.Where(sq.Eq{
|
||||
LockoutColID.identifier(): q.iamID,
|
||||
LockoutColID.identifier(): domain.IAMID,
|
||||
}).
|
||||
OrderBy(LockoutColIsDefault.identifier()).
|
||||
Limit(1).ToSql()
|
||||
|
@ -65,7 +65,7 @@ func (q *Queries) MailTemplateByOrg(ctx context.Context, orgID string) (*MailTem
|
||||
MailTemplateColAggregateID.identifier(): orgID,
|
||||
},
|
||||
sq.Eq{
|
||||
MailTemplateColAggregateID.identifier(): q.iamID,
|
||||
MailTemplateColAggregateID.identifier(): domain.IAMID,
|
||||
},
|
||||
}).
|
||||
OrderBy(MailTemplateColIsDefault.identifier()).
|
||||
@ -81,7 +81,7 @@ func (q *Queries) MailTemplateByOrg(ctx context.Context, orgID string) (*MailTem
|
||||
func (q *Queries) DefaultMailTemplate(ctx context.Context) (*MailTemplate, error) {
|
||||
stmt, scan := prepareMailTemplateQuery()
|
||||
query, args, err := stmt.Where(sq.Eq{
|
||||
MailTemplateColAggregateID.identifier(): q.iamID,
|
||||
MailTemplateColAggregateID.identifier(): domain.IAMID,
|
||||
}).
|
||||
OrderBy(MailTemplateColIsDefault.identifier()).
|
||||
Limit(1).ToSql()
|
||||
|
@ -119,7 +119,7 @@ func (q *Queries) MessageTextByOrg(ctx context.Context, orgID string) (*MessageT
|
||||
MessageTextColAggregateID.identifier(): orgID,
|
||||
},
|
||||
sq.Eq{
|
||||
MessageTextColAggregateID.identifier(): q.iamID,
|
||||
MessageTextColAggregateID.identifier(): domain.IAMID,
|
||||
},
|
||||
}).
|
||||
OrderBy(MessageTextColAggregateID.identifier()).
|
||||
@ -135,7 +135,7 @@ func (q *Queries) MessageTextByOrg(ctx context.Context, orgID string) (*MessageT
|
||||
func (q *Queries) DefaultMessageText(ctx context.Context) (*MessageText, error) {
|
||||
stmt, scan := prepareMessageTextQuery()
|
||||
query, args, err := stmt.Where(sq.Eq{
|
||||
MessageTextColAggregateID.identifier(): q.iamID,
|
||||
MessageTextColAggregateID.identifier(): domain.IAMID,
|
||||
}).
|
||||
Limit(1).ToSql()
|
||||
if err != nil {
|
||||
@ -230,7 +230,7 @@ func (q *Queries) readNotificationTextMessages(language string) ([]byte, error)
|
||||
if !ok {
|
||||
contents, err = q.readTranslationFile(q.NotificationDir, fmt.Sprintf("/i18n/%s.yaml", language))
|
||||
if errors.IsNotFound(err) {
|
||||
contents, err = q.readTranslationFile(q.NotificationDir, fmt.Sprintf("/i18n/%s.yaml", q.DefaultLanguage.String()))
|
||||
contents, err = q.readTranslationFile(q.NotificationDir, fmt.Sprintf("/i18n/%s.yaml", q.GetDefaultLanguage(context.Background()).String()))
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -71,7 +71,7 @@ func (q *Queries) OrgIAMPolicyByOrg(ctx context.Context, orgID string) (*OrgIAMP
|
||||
OrgIAMColID.identifier(): orgID,
|
||||
},
|
||||
sq.Eq{
|
||||
OrgIAMColID.identifier(): q.iamID,
|
||||
OrgIAMColID.identifier(): domain.IAMID,
|
||||
},
|
||||
}).
|
||||
OrderBy(OrgIAMColIsDefault.identifier()).
|
||||
@ -87,7 +87,7 @@ func (q *Queries) OrgIAMPolicyByOrg(ctx context.Context, orgID string) (*OrgIAMP
|
||||
func (q *Queries) DefaultOrgIAMPolicy(ctx context.Context) (*OrgIAMPolicy, error) {
|
||||
stmt, scan := prepareOrgIAMPolicyQuery()
|
||||
query, args, err := stmt.Where(sq.Eq{
|
||||
OrgIAMColID.identifier(): q.iamID,
|
||||
OrgIAMColID.identifier(): domain.IAMID,
|
||||
}).
|
||||
OrderBy(OrgIAMColIsDefault.identifier()).
|
||||
Limit(1).ToSql()
|
||||
|
@ -76,7 +76,7 @@ func (q *Queries) PasswordAgePolicyByOrg(ctx context.Context, orgID string) (*Pa
|
||||
PasswordAgeColID.identifier(): orgID,
|
||||
},
|
||||
sq.Eq{
|
||||
PasswordAgeColID.identifier(): q.iamID,
|
||||
PasswordAgeColID.identifier(): domain.IAMID,
|
||||
},
|
||||
}).
|
||||
OrderBy(PasswordAgeColIsDefault.identifier()).
|
||||
@ -92,7 +92,7 @@ func (q *Queries) PasswordAgePolicyByOrg(ctx context.Context, orgID string) (*Pa
|
||||
func (q *Queries) DefaultPasswordAgePolicy(ctx context.Context) (*PasswordAgePolicy, error) {
|
||||
stmt, scan := preparePasswordAgePolicyQuery()
|
||||
query, args, err := stmt.Where(sq.Eq{
|
||||
PasswordAgeColID.identifier(): q.iamID,
|
||||
PasswordAgeColID.identifier(): domain.IAMID,
|
||||
}).
|
||||
OrderBy(PasswordAgeColIsDefault.identifier()).
|
||||
Limit(1).ToSql()
|
||||
|
@ -37,7 +37,7 @@ func (q *Queries) PasswordComplexityPolicyByOrg(ctx context.Context, orgID strin
|
||||
PasswordComplexityColID.identifier(): orgID,
|
||||
},
|
||||
sq.Eq{
|
||||
PasswordComplexityColID.identifier(): q.iamID,
|
||||
PasswordComplexityColID.identifier(): domain.IAMID,
|
||||
},
|
||||
}).
|
||||
OrderBy(PasswordComplexityColIsDefault.identifier()).
|
||||
@ -53,7 +53,7 @@ func (q *Queries) PasswordComplexityPolicyByOrg(ctx context.Context, orgID strin
|
||||
func (q *Queries) DefaultPasswordComplexityPolicy(ctx context.Context) (*PasswordComplexityPolicy, error) {
|
||||
stmt, scan := preparePasswordComplexityPolicyQuery()
|
||||
query, args, err := stmt.Where(sq.Eq{
|
||||
PasswordComplexityColID.identifier(): q.iamID,
|
||||
PasswordComplexityColID.identifier(): domain.IAMID,
|
||||
}).
|
||||
OrderBy(PasswordComplexityColIsDefault.identifier()).
|
||||
Limit(1).ToSql()
|
||||
|
@ -76,7 +76,7 @@ func (q *Queries) PrivacyPolicyByOrg(ctx context.Context, orgID string) (*Privac
|
||||
PrivacyColID.identifier(): orgID,
|
||||
},
|
||||
sq.Eq{
|
||||
PrivacyColID.identifier(): q.iamID,
|
||||
PrivacyColID.identifier(): domain.IAMID,
|
||||
},
|
||||
}).
|
||||
OrderBy(PrivacyColIsDefault.identifier()).
|
||||
@ -92,7 +92,7 @@ func (q *Queries) PrivacyPolicyByOrg(ctx context.Context, orgID string) (*Privac
|
||||
func (q *Queries) DefaultPrivacyPolicy(ctx context.Context) (*PrivacyPolicy, error) {
|
||||
stmt, scan := preparePrivacyPolicyQuery()
|
||||
query, args, err := stmt.Where(sq.Eq{
|
||||
PrivacyColID.identifier(): q.iamID,
|
||||
PrivacyColID.identifier(): domain.IAMID,
|
||||
}).
|
||||
OrderBy(PrivacyColIsDefault.identifier()).
|
||||
Limit(1).ToSql()
|
||||
|
@ -40,6 +40,10 @@ func (p *IAMProjection) reducers() []handler.AggregateReducer {
|
||||
Event: iam.ProjectSetEventType,
|
||||
Reduce: p.reduceIAMProjectSet,
|
||||
},
|
||||
{
|
||||
Event: iam.DefaultLanguageSetEventType,
|
||||
Reduce: p.reduceDefaultLanguageSet,
|
||||
},
|
||||
{
|
||||
Event: iam.SetupStartedEventType,
|
||||
Reduce: p.reduceSetupEvent,
|
||||
@ -56,13 +60,14 @@ func (p *IAMProjection) reducers() []handler.AggregateReducer {
|
||||
type IAMColumn string
|
||||
|
||||
const (
|
||||
IAMColumnID = "id"
|
||||
IAMColumnChangeDate = "change_date"
|
||||
IAMColumnGlobalOrgID = "global_org_id"
|
||||
IAMColumnProjectID = "iam_project_id"
|
||||
IAMColumnSequence = "sequence"
|
||||
IAMColumnSetUpStarted = "setup_started"
|
||||
IAMColumnSetUpDone = "setup_done"
|
||||
IAMColumnID = "id"
|
||||
IAMColumnChangeDate = "change_date"
|
||||
IAMColumnGlobalOrgID = "global_org_id"
|
||||
IAMColumnProjectID = "iam_project_id"
|
||||
IAMColumnSequence = "sequence"
|
||||
IAMColumnSetUpStarted = "setup_started"
|
||||
IAMColumnSetUpDone = "setup_done"
|
||||
IAMColumnDefaultLanguage = "default_language"
|
||||
)
|
||||
|
||||
func (p *IAMProjection) reduceGlobalOrgSet(event eventstore.Event) (*handler.Statement, error) {
|
||||
@ -99,6 +104,23 @@ func (p *IAMProjection) reduceIAMProjectSet(event eventstore.Event) (*handler.St
|
||||
), nil
|
||||
}
|
||||
|
||||
func (p *IAMProjection) reduceDefaultLanguageSet(event eventstore.Event) (*handler.Statement, error) {
|
||||
e, ok := event.(*iam.DefaultLanguageSetEvent)
|
||||
if !ok {
|
||||
logging.LogWithFields("HANDL-3n9le", "seq", event.Sequence(), "expectedType", iam.DefaultLanguageSetEventType).Error("wrong event type")
|
||||
return nil, errors.ThrowInvalidArgument(nil, "HANDL-30o0e", "reduce.wrong.event.type")
|
||||
}
|
||||
return crdb.NewUpsertStatement(
|
||||
e,
|
||||
[]handler.Column{
|
||||
handler.NewCol(IAMColumnID, e.Aggregate().ID),
|
||||
handler.NewCol(IAMColumnChangeDate, e.CreationDate()),
|
||||
handler.NewCol(IAMColumnSequence, e.Sequence()),
|
||||
handler.NewCol(IAMColumnDefaultLanguage, e.Language.String()),
|
||||
},
|
||||
), nil
|
||||
}
|
||||
|
||||
func (p *IAMProjection) reduceSetupEvent(event eventstore.Event) (*handler.Statement, error) {
|
||||
e, ok := event.(*iam.SetupStepEvent)
|
||||
if !ok {
|
||||
|
@ -52,7 +52,7 @@ func TestIAMProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "reduceGlobalOrgSet",
|
||||
name: "reduceProjectIDSet",
|
||||
args: args{
|
||||
event: getEvent(testEvent(
|
||||
repository.EventType(iam.ProjectSetEventType),
|
||||
@ -81,6 +81,36 @@ func TestIAMProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "reduceDefaultLanguageSet",
|
||||
args: args{
|
||||
event: getEvent(testEvent(
|
||||
repository.EventType(iam.DefaultLanguageSetEventType),
|
||||
iam.AggregateType,
|
||||
[]byte(`{"language": "en"}`),
|
||||
), iam.DefaultLanguageSetMapper),
|
||||
},
|
||||
reduce: (&IAMProjection{}).reduceDefaultLanguageSet,
|
||||
want: wantReduce{
|
||||
projection: IAMProjectionTable,
|
||||
aggregateType: eventstore.AggregateType("iam"),
|
||||
sequence: 15,
|
||||
previousSequence: 10,
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPSERT INTO zitadel.projections.iam (id, change_date, sequence, default_language) VALUES ($1, $2, $3, $4)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
"en",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "reduceSetupStarted",
|
||||
args: args{
|
||||
|
@ -69,6 +69,8 @@ func Start(ctx context.Context, sqlClient *sql.DB, es *eventstore.Eventstore, co
|
||||
NewUserMetadataProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["user_metadata"]))
|
||||
NewUserAuthMethodProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["user_auth_method"]))
|
||||
NewIAMProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["iam"]))
|
||||
NewSecretGeneratorProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["secret_generators"]))
|
||||
NewSMTPConfigProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["smtp_configs"]))
|
||||
_, err := NewKeyProjection(ctx, applyCustomConfig(projectionConfig, config.Customizations["keys"]), keyConfig, keyChan)
|
||||
|
||||
return err
|
||||
|
144
internal/query/projection/secret_generator.go
Normal file
144
internal/query/projection/secret_generator.go
Normal file
@ -0,0 +1,144 @@
|
||||
package projection
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/caos/logging"
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore"
|
||||
"github.com/caos/zitadel/internal/eventstore/handler"
|
||||
"github.com/caos/zitadel/internal/eventstore/handler/crdb"
|
||||
"github.com/caos/zitadel/internal/repository/iam"
|
||||
"github.com/caos/zitadel/internal/repository/project"
|
||||
)
|
||||
|
||||
type SecretGeneratorProjection struct {
|
||||
crdb.StatementHandler
|
||||
}
|
||||
|
||||
const (
|
||||
SecretGeneratorProjectionTable = "zitadel.projections.secret_generators"
|
||||
)
|
||||
|
||||
func NewSecretGeneratorProjection(ctx context.Context, config crdb.StatementHandlerConfig) *SecretGeneratorProjection {
|
||||
p := &SecretGeneratorProjection{}
|
||||
config.ProjectionName = SecretGeneratorProjectionTable
|
||||
config.Reducers = p.reducers()
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
return p
|
||||
}
|
||||
|
||||
func (p *SecretGeneratorProjection) reducers() []handler.AggregateReducer {
|
||||
return []handler.AggregateReducer{
|
||||
{
|
||||
Aggregate: project.AggregateType,
|
||||
EventRedusers: []handler.EventReducer{
|
||||
{
|
||||
Event: iam.SecretGeneratorAddedEventType,
|
||||
Reduce: p.reduceSecretGeneratorAdded,
|
||||
},
|
||||
{
|
||||
Event: iam.SecretGeneratorChangedEventType,
|
||||
Reduce: p.reduceSecretGeneratorChanged,
|
||||
},
|
||||
{
|
||||
Event: iam.SecretGeneratorRemovedEventType,
|
||||
Reduce: p.reduceSecretGeneratorRemoved,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
SecretGeneratorColumnGeneratorType = "generator_type"
|
||||
SecretGeneratorColumnAggregateID = "aggregate_id"
|
||||
SecretGeneratorColumnCreationDate = "creation_date"
|
||||
SecretGeneratorColumnChangeDate = "change_date"
|
||||
SecretGeneratorColumnResourceOwner = "resource_owner"
|
||||
SecretGeneratorColumnSequence = "sequence"
|
||||
SecretGeneratorColumnLength = "length"
|
||||
SecretGeneratorColumnExpiry = "expiry"
|
||||
SecretGeneratorColumnIncludeLowerLetters = "include_lower_letters"
|
||||
SecretGeneratorColumnIncludeUpperLetters = "include_upper_letters"
|
||||
SecretGeneratorColumnIncludeDigits = "include_digits"
|
||||
SecretGeneratorColumnIncludeSymbols = "include_symbols"
|
||||
)
|
||||
|
||||
func (p *SecretGeneratorProjection) reduceSecretGeneratorAdded(event eventstore.Event) (*handler.Statement, error) {
|
||||
e, ok := event.(*iam.SecretGeneratorAddedEvent)
|
||||
if !ok {
|
||||
logging.LogWithFields("HANDL-nf9sl", "seq", event.Sequence(), "expectedType", iam.SecretGeneratorAddedEventType).Error("wrong event type")
|
||||
return nil, errors.ThrowInvalidArgument(nil, "HANDL-sk99F", "reduce.wrong.event.type")
|
||||
}
|
||||
return crdb.NewCreateStatement(
|
||||
e,
|
||||
[]handler.Column{
|
||||
handler.NewCol(SecretGeneratorColumnAggregateID, e.Aggregate().ID),
|
||||
handler.NewCol(SecretGeneratorColumnGeneratorType, e.GeneratorType),
|
||||
handler.NewCol(SecretGeneratorColumnCreationDate, e.CreationDate()),
|
||||
handler.NewCol(SecretGeneratorColumnChangeDate, e.CreationDate()),
|
||||
handler.NewCol(SecretGeneratorColumnResourceOwner, e.Aggregate().ResourceOwner),
|
||||
handler.NewCol(SecretGeneratorColumnSequence, e.Sequence()),
|
||||
handler.NewCol(SecretGeneratorColumnLength, e.Length),
|
||||
handler.NewCol(SecretGeneratorColumnExpiry, e.Expiry),
|
||||
handler.NewCol(SecretGeneratorColumnIncludeLowerLetters, e.IncludeLowerLetters),
|
||||
handler.NewCol(SecretGeneratorColumnIncludeUpperLetters, e.IncludeUpperLetters),
|
||||
handler.NewCol(SecretGeneratorColumnIncludeDigits, e.IncludeDigits),
|
||||
handler.NewCol(SecretGeneratorColumnIncludeSymbols, e.IncludeSymbols),
|
||||
},
|
||||
), nil
|
||||
}
|
||||
|
||||
func (p *SecretGeneratorProjection) reduceSecretGeneratorChanged(event eventstore.Event) (*handler.Statement, error) {
|
||||
e, ok := event.(*iam.SecretGeneratorChangedEvent)
|
||||
if !ok {
|
||||
logging.LogWithFields("HANDL-sn9jd", "seq", event.Sequence(), "expected", iam.SecretGeneratorChangedEventType).Error("wrong event type")
|
||||
return nil, errors.ThrowInvalidArgument(nil, "HANDL-s00Fs", "reduce.wrong.event.type")
|
||||
}
|
||||
|
||||
columns := make([]handler.Column, 0, 7)
|
||||
columns = append(columns, handler.NewCol(SecretGeneratorColumnChangeDate, e.CreationDate()),
|
||||
handler.NewCol(SecretGeneratorColumnSequence, e.Sequence()))
|
||||
if e.Length != nil {
|
||||
columns = append(columns, handler.NewCol(SecretGeneratorColumnLength, *e.Length))
|
||||
}
|
||||
if e.Expiry != nil {
|
||||
columns = append(columns, handler.NewCol(SecretGeneratorColumnExpiry, *e.Expiry))
|
||||
}
|
||||
if e.IncludeLowerLetters != nil {
|
||||
columns = append(columns, handler.NewCol(SecretGeneratorColumnIncludeLowerLetters, *e.IncludeLowerLetters))
|
||||
}
|
||||
if e.IncludeUpperLetters != nil {
|
||||
columns = append(columns, handler.NewCol(SecretGeneratorColumnIncludeUpperLetters, *e.IncludeUpperLetters))
|
||||
}
|
||||
if e.IncludeDigits != nil {
|
||||
columns = append(columns, handler.NewCol(SecretGeneratorColumnIncludeDigits, *e.IncludeDigits))
|
||||
}
|
||||
if e.IncludeSymbols != nil {
|
||||
columns = append(columns, handler.NewCol(SecretGeneratorColumnIncludeSymbols, *e.IncludeSymbols))
|
||||
}
|
||||
return crdb.NewUpdateStatement(
|
||||
e,
|
||||
columns,
|
||||
[]handler.Condition{
|
||||
handler.NewCond(SecretGeneratorColumnAggregateID, e.Aggregate().ID),
|
||||
handler.NewCond(SecretGeneratorColumnGeneratorType, e.GeneratorType),
|
||||
},
|
||||
), nil
|
||||
}
|
||||
|
||||
func (p *SecretGeneratorProjection) reduceSecretGeneratorRemoved(event eventstore.Event) (*handler.Statement, error) {
|
||||
e, ok := event.(*iam.SecretGeneratorRemovedEvent)
|
||||
if !ok {
|
||||
logging.LogWithFields("HANDL-30oEF", "seq", event.Sequence(), "expectedType", iam.SecretGeneratorRemovedEventType).Error("wrong event type")
|
||||
return nil, errors.ThrowInvalidArgument(nil, "HANDL-fmiIf", "reduce.wrong.event.type")
|
||||
}
|
||||
return crdb.NewDeleteStatement(
|
||||
e,
|
||||
[]handler.Condition{
|
||||
handler.NewCond(SecretGeneratorColumnAggregateID, e.Aggregate().ID),
|
||||
handler.NewCond(SecretGeneratorColumnGeneratorType, e.GeneratorType),
|
||||
},
|
||||
), nil
|
||||
}
|
141
internal/query/projection/secret_generator_test.go
Normal file
141
internal/query/projection/secret_generator_test.go
Normal file
@ -0,0 +1,141 @@
|
||||
package projection
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore"
|
||||
"github.com/caos/zitadel/internal/eventstore/handler"
|
||||
"github.com/caos/zitadel/internal/eventstore/repository"
|
||||
"github.com/caos/zitadel/internal/repository/iam"
|
||||
)
|
||||
|
||||
func TestSecretGeneratorProjection_reduces(t *testing.T) {
|
||||
type args struct {
|
||||
event func(t *testing.T) eventstore.Event
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
reduce func(event eventstore.Event) (*handler.Statement, error)
|
||||
want wantReduce
|
||||
}{
|
||||
{
|
||||
name: "reduceSecretGeneratorRemoved",
|
||||
args: args{
|
||||
event: getEvent(testEvent(
|
||||
repository.EventType(iam.SecretGeneratorRemovedEventType),
|
||||
iam.AggregateType,
|
||||
[]byte(`{"generatorType": 1}`),
|
||||
), iam.SecretGeneratorRemovedEventMapper),
|
||||
},
|
||||
reduce: (&SecretGeneratorProjection{}).reduceSecretGeneratorRemoved,
|
||||
want: wantReduce{
|
||||
projection: SecretGeneratorProjectionTable,
|
||||
aggregateType: eventstore.AggregateType("iam"),
|
||||
sequence: 15,
|
||||
previousSequence: 10,
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "DELETE FROM zitadel.projections.secret_generators WHERE (aggregate_id = $1) AND (generator_type = $2)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
domain.SecretGeneratorTypeInitCode,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "reduceSecretGeneratorChanged",
|
||||
args: args{
|
||||
event: getEvent(testEvent(
|
||||
repository.EventType(iam.SecretGeneratorChangedEventType),
|
||||
iam.AggregateType,
|
||||
[]byte(`{"generatorType": 1, "length": 4, "expiry": 10000000, "includeLowerLetters": true, "includeUpperLetters": true, "includeDigits": true, "includeSymbols": true}`),
|
||||
), iam.SecretGeneratorChangedEventMapper),
|
||||
},
|
||||
reduce: (&SecretGeneratorProjection{}).reduceSecretGeneratorChanged,
|
||||
want: wantReduce{
|
||||
projection: SecretGeneratorProjectionTable,
|
||||
aggregateType: eventstore.AggregateType("iam"),
|
||||
sequence: 15,
|
||||
previousSequence: 10,
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE zitadel.projections.secret_generators SET (change_date, sequence, length, expiry, include_lower_letters, include_upper_letters, include_digits, include_symbols) = ($1, $2, $3, $4, $5, $6, $7, $8) WHERE (aggregate_id = $9) AND (generator_type = $10)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
uint(4),
|
||||
time.Millisecond * 10,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
"agg-id",
|
||||
domain.SecretGeneratorTypeInitCode,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "reduceSecretGeneratorAdded",
|
||||
args: args{
|
||||
event: getEvent(testEvent(
|
||||
repository.EventType(iam.SecretGeneratorAddedEventType),
|
||||
iam.AggregateType,
|
||||
[]byte(`{"generatorType": 1, "length": 4, "expiry": 10000000, "includeLowerLetters": true, "includeUpperLetters": true, "includeDigits": true, "includeSymbols": true}`),
|
||||
), iam.SecretGeneratorAddedEventMapper),
|
||||
},
|
||||
reduce: (&SecretGeneratorProjection{}).reduceSecretGeneratorAdded,
|
||||
want: wantReduce{
|
||||
projection: SecretGeneratorProjectionTable,
|
||||
aggregateType: eventstore.AggregateType("iam"),
|
||||
sequence: 15,
|
||||
previousSequence: 10,
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "INSERT INTO zitadel.projections.secret_generators (aggregate_id, generator_type, creation_date, change_date, resource_owner, sequence, length, expiry, include_lower_letters, include_upper_letters, include_digits, include_symbols) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
domain.SecretGeneratorTypeInitCode,
|
||||
anyArg{},
|
||||
anyArg{},
|
||||
"ro-id",
|
||||
uint64(15),
|
||||
uint(4),
|
||||
time.Millisecond * 10,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
event := baseEvent(t)
|
||||
got, err := tt.reduce(event)
|
||||
if _, ok := err.(errors.InvalidArgument); !ok {
|
||||
t.Errorf("no wrong event mapping: %v, got: %v", err, got)
|
||||
}
|
||||
|
||||
event = tt.args.event(t)
|
||||
got, err = tt.reduce(event)
|
||||
assertReduce(t, got, err, tt.want)
|
||||
})
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user