feat: support client_credentials for service users (#5134)

Request an access_token for service users with OAuth 2.0 Client Credentials Grant. Added functionality to generate and remove a secret on service users.
This commit is contained in:
Stefan Benz
2023-01-31 20:52:47 +01:00
committed by GitHub
parent 7c7c93117b
commit e2fdd3f077
48 changed files with 2113 additions and 311 deletions

View File

@@ -756,6 +756,34 @@ func (s *Server) RemoveMachineKey(ctx context.Context, req *mgmt_pb.RemoveMachin
}, nil
}
func (s *Server) GenerateMachineSecret(ctx context.Context, req *mgmt_pb.GenerateMachineSecretRequest) (*mgmt_pb.GenerateMachineSecretResponse, error) {
// use SecretGeneratorTypeAppSecret as the secrets will be used in the client_credentials grant like a client secret
secretGenerator, err := s.query.InitHashGenerator(ctx, domain.SecretGeneratorTypeAppSecret, s.passwordHashAlg)
if err != nil {
return nil, err
}
set := new(command.GenerateMachineSecret)
details, err := s.command.GenerateMachineSecret(ctx, req.UserId, authz.GetCtxData(ctx).OrgID, secretGenerator, set)
if err != nil {
return nil, err
}
return &mgmt_pb.GenerateMachineSecretResponse{
ClientId: set.ClientID,
ClientSecret: set.ClientSecret,
Details: obj_grpc.DomainToAddDetailsPb(details),
}, nil
}
func (s *Server) RemoveMachineSecret(ctx context.Context, req *mgmt_pb.RemoveMachineSecretRequest) (*mgmt_pb.RemoveMachineSecretResponse, error) {
objectDetails, err := s.command.RemoveMachineSecret(ctx, req.UserId, authz.GetCtxData(ctx).OrgID)
if err != nil {
return nil, err
}
return &mgmt_pb.RemoveMachineSecretResponse{
Details: obj_grpc.DomainToChangeDetailsPb(objectDetails),
}, nil
}
func (s *Server) GetPersonalAccessTokenByIDs(ctx context.Context, req *mgmt_pb.GetPersonalAccessTokenByIDsRequest) (*mgmt_pb.GetPersonalAccessTokenByIDsResponse, error) {
resourceOwner, err := query.NewPersonalAccessTokenResourceOwnerSearchQuery(authz.GetCtxData(ctx).OrgID)
if err != nil {

View File

@@ -72,6 +72,7 @@ func MachineToPb(view *query.Machine) *user_pb.Machine {
return &user_pb.Machine{
Name: view.Name,
Description: view.Description,
HasSecret: view.HasSecret,
}
}

View File

@@ -94,29 +94,7 @@ func (o *OPStorage) ValidateJWTProfileScopes(ctx context.Context, subject string
if err != nil {
return nil, err
}
for i := len(scopes) - 1; i >= 0; i-- {
scope := scopes[i]
if strings.HasPrefix(scope, domain.OrgDomainPrimaryScope) {
var orgID string
org, err := o.query.OrgByPrimaryDomain(ctx, strings.TrimPrefix(scope, domain.OrgDomainPrimaryScope))
if err == nil {
orgID = org.ID
}
if orgID != user.ResourceOwner {
scopes[i] = scopes[len(scopes)-1]
scopes[len(scopes)-1] = ""
scopes = scopes[:len(scopes)-1]
}
}
if strings.HasPrefix(scope, domain.OrgIDScope) {
if strings.TrimPrefix(scope, domain.OrgIDScope) != user.ResourceOwner {
scopes[i] = scopes[len(scopes)-1]
scopes[len(scopes)-1] = ""
scopes = scopes[:len(scopes)-1]
}
}
}
return scopes, nil
return o.checkOrgScopes(ctx, user, scopes)
}
func (o *OPStorage) AuthorizeClientIDSecret(ctx context.Context, id string, secret string) (err error) {
@@ -209,6 +187,68 @@ func (o *OPStorage) SetIntrospectionFromToken(ctx context.Context, introspection
return errors.ThrowPermissionDenied(nil, "OIDC-sdg3G", "token is not valid for this client")
}
func (o *OPStorage) ClientCredentialsTokenRequest(ctx context.Context, clientID string, scope []string) (op.TokenRequest, error) {
loginname, err := query.NewUserLoginNamesSearchQuery(clientID)
if err != nil {
return nil, err
}
user, err := o.query.GetUser(ctx, false, false, loginname)
if err != nil {
return nil, err
}
scope, err = o.checkOrgScopes(ctx, user, scope)
if err != nil {
return nil, err
}
return &clientCredentialsRequest{
sub: user.ID,
scopes: scope,
}, nil
}
func (o *OPStorage) ClientCredentials(ctx context.Context, clientID, clientSecret string) (op.Client, error) {
loginname, err := query.NewUserLoginNamesSearchQuery(clientID)
if err != nil {
return nil, err
}
user, err := o.query.GetUser(ctx, false, false, loginname)
if err != nil {
return nil, err
}
if _, err := o.command.VerifyMachineSecret(ctx, user.ID, user.ResourceOwner, clientSecret); err != nil {
return nil, err
}
return &clientCredentialsClient{
id: clientID,
}, nil
}
func (o *OPStorage) checkOrgScopes(ctx context.Context, user *query.User, scopes []string) ([]string, error) {
for i := len(scopes) - 1; i >= 0; i-- {
scope := scopes[i]
if strings.HasPrefix(scope, domain.OrgDomainPrimaryScope) {
var orgID string
org, err := o.query.OrgByPrimaryDomain(ctx, strings.TrimPrefix(scope, domain.OrgDomainPrimaryScope))
if err == nil {
orgID = org.ID
}
if orgID != user.ResourceOwner {
scopes[i] = scopes[len(scopes)-1]
scopes[len(scopes)-1] = ""
scopes = scopes[:len(scopes)-1]
}
}
if strings.HasPrefix(scope, domain.OrgIDScope) {
if strings.TrimPrefix(scope, domain.OrgIDScope) != user.ResourceOwner {
scopes[i] = scopes[len(scopes)-1]
scopes[len(scopes)-1] = ""
scopes = scopes[:len(scopes)-1]
}
}
}
return scopes, nil
}
func (o *OPStorage) setUserinfo(ctx context.Context, userInfo oidc.UserInfoSetter, userID, applicationID string, scopes []string) (err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()

View File

@@ -0,0 +1,120 @@
package oidc
import (
"time"
"github.com/zitadel/oidc/v2/pkg/oidc"
"github.com/zitadel/oidc/v2/pkg/op"
)
type clientCredentialsRequest struct {
sub string
scopes []string
}
func (c *clientCredentialsRequest) GetSubject() string {
return c.sub
}
// GetAudience returns the audience for token to be created because of the client credentials request
// return nil as the audience is set during the token creation in command.addUserToken
func (c *clientCredentialsRequest) GetAudience() []string {
return nil
}
func (c *clientCredentialsRequest) GetScopes() []string {
return c.scopes
}
type clientCredentialsClient struct {
id string
}
// AccessTokenType returns the AccessTokenType for the token to be created because of the client credentials request
// machine users currently only have opaque tokens ([op.AccessTokenTypeBearer])
func (c *clientCredentialsClient) AccessTokenType() op.AccessTokenType {
return op.AccessTokenTypeBearer
}
// GetID returns the client_id (username of the machine user) for the token to be created because of the client credentials request
func (c *clientCredentialsClient) GetID() string {
return c.id
}
// RedirectURIs returns nil as there are no redirect uris
func (c *clientCredentialsClient) RedirectURIs() []string {
return nil
}
// PostLogoutRedirectURIs returns nil as there are no logout redirect uris
func (c *clientCredentialsClient) PostLogoutRedirectURIs() []string {
return nil
}
// ApplicationType returns [op.ApplicationTypeWeb] as the machine users is a confidential client
func (c *clientCredentialsClient) ApplicationType() op.ApplicationType {
return op.ApplicationTypeWeb
}
// AuthMethod returns the allowed auth method type for machine user.
// It returns Basic Auth
func (c *clientCredentialsClient) AuthMethod() oidc.AuthMethod {
return oidc.AuthMethodBasic
}
// ResponseTypes returns nil as the types are only required for an authorization request
func (c *clientCredentialsClient) ResponseTypes() []oidc.ResponseType {
return nil
}
// GrantTypes returns the grant types supported by the machine users, which is currently only client credentials ([oidc.GrantTypeClientCredentials])
func (c *clientCredentialsClient) GrantTypes() []oidc.GrantType {
return []oidc.GrantType{
oidc.GrantTypeClientCredentials,
}
}
// LoginURL returns an empty string as there is no login UI involved
func (c *clientCredentialsClient) LoginURL(_ string) string {
return ""
}
// IDTokenLifetime returns 0 as there is no id_token issued
func (c *clientCredentialsClient) IDTokenLifetime() time.Duration {
return 0
}
// DevMode returns false as there is no dev mode
func (c *clientCredentialsClient) DevMode() bool {
return false
}
// RestrictAdditionalIdTokenScopes returns nil as no id_token is issued
func (c *clientCredentialsClient) RestrictAdditionalIdTokenScopes() func(scopes []string) []string {
return nil
}
// RestrictAdditionalAccessTokenScopes returns the scope allowed for the token to be created because of the client credentials request
// currently it allows all scopes to be used in the access token
func (c *clientCredentialsClient) RestrictAdditionalAccessTokenScopes() func(scopes []string) []string {
return func(scopes []string) []string {
return scopes
}
}
// IsScopeAllowed returns null false as the check is executed during the auth request validation
func (c *clientCredentialsClient) IsScopeAllowed(scope string) bool {
return false
}
// IDTokenUserinfoClaimsAssertion returns null false as no id_token is issued
func (c *clientCredentialsClient) IDTokenUserinfoClaimsAssertion() bool {
return false
}
// ClockSkew enable handling clock skew of the token validation. The duration (0-5s) will be added to exp claim and subtracted from iats,
// auth_time and nbf of the token to be created because of the client credentials request.
// It returns 0 as clock skew is not implemented on machine users.
func (c *clientCredentialsClient) ClockSkew() time.Duration {
return 0
}

View File

@@ -3,6 +3,7 @@ package command
import (
"context"
"github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/domain"
@@ -17,6 +18,8 @@ type MachineWriteModel struct {
Name string
Description string
UserState domain.UserState
ClientSecret *crypto.CryptoValue
}
func NewMachineWriteModel(userID, resourceOwner string) *MachineWriteModel {
@@ -63,6 +66,10 @@ func (wm *MachineWriteModel) Reduce() error {
}
case *user.UserRemovedEvent:
wm.UserState = domain.UserStateDeleted
case *user.MachineSecretSetEvent:
wm.ClientSecret = e.ClientSecret
case *user.MachineSecretRemovedEvent:
wm.ClientSecret = nil
}
}
return wm.WriteModel.Reduce()
@@ -81,7 +88,9 @@ func (wm *MachineWriteModel) Query() *eventstore.SearchQueryBuilder {
user.UserUnlockedType,
user.UserDeactivatedType,
user.UserReactivatedType,
user.UserRemovedType).
user.UserRemovedType,
user.MachineSecretSetType,
user.MachineSecretRemovedType).
Builder()
}

View File

@@ -0,0 +1,171 @@
package command
import (
"context"
"github.com/zitadel/logging"
"github.com/zitadel/zitadel/internal/command/preparation"
"github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/domain"
caos_errs "github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/repository/user"
)
type GenerateMachineSecret struct {
ClientID string
ClientSecret string
}
func (c *Commands) GenerateMachineSecret(ctx context.Context, userID string, resourceOwner string, generator crypto.Generator, set *GenerateMachineSecret) (*domain.ObjectDetails, error) {
agg := user.NewAggregate(userID, resourceOwner)
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, prepareGenerateMachineSecret(agg, generator, set))
if err != nil {
return nil, err
}
events, err := c.eventstore.Push(ctx, cmds...)
if err != nil {
return nil, err
}
return &domain.ObjectDetails{
Sequence: events[len(events)-1].Sequence(),
EventDate: events[len(events)-1].CreationDate(),
ResourceOwner: events[len(events)-1].Aggregate().ResourceOwner,
}, nil
}
func prepareGenerateMachineSecret(a *user.Aggregate, generator crypto.Generator, set *GenerateMachineSecret) preparation.Validation {
return func() (_ preparation.CreateCommands, err error) {
if a.ResourceOwner == "" {
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-x0992n", "Errors.ResourceOwnerMissing")
}
if a.ID == "" {
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-bzoqjs", "Errors.User.UserIDMissing")
}
return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
writeModel, err := getMachineWriteModel(ctx, a.ID, a.ResourceOwner, filter)
if err != nil {
return nil, err
}
if !isUserStateExists(writeModel.UserState) {
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-x8910n", "Errors.User.NotExisting")
}
set.ClientID = writeModel.UserName
clientSecret, secretString, err := domain.NewMachineClientSecret(generator)
if err != nil {
return nil, err
}
set.ClientSecret = secretString
return []eventstore.Command{
user.NewMachineSecretSetEvent(ctx, &a.Aggregate, clientSecret),
}, nil
}, nil
}
}
func (c *Commands) RemoveMachineSecret(ctx context.Context, userID string, resourceOwner string) (*domain.ObjectDetails, error) {
agg := user.NewAggregate(userID, resourceOwner)
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, prepareRemoveMachineSecret(agg))
if err != nil {
return nil, err
}
events, err := c.eventstore.Push(ctx, cmds...)
if err != nil {
return nil, err
}
return &domain.ObjectDetails{
Sequence: events[len(events)-1].Sequence(),
EventDate: events[len(events)-1].CreationDate(),
ResourceOwner: events[len(events)-1].Aggregate().ResourceOwner,
}, nil
}
func prepareRemoveMachineSecret(a *user.Aggregate) preparation.Validation {
return func() (_ preparation.CreateCommands, err error) {
if a.ResourceOwner == "" {
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-0qp2hus", "Errors.ResourceOwnerMissing")
}
if a.ID == "" {
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-bzosjs", "Errors.User.UserIDMissing")
}
return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
writeModel, err := getMachineWriteModel(ctx, a.ID, a.ResourceOwner, filter)
if err != nil {
return nil, err
}
if !isUserStateExists(writeModel.UserState) {
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-x7s802", "Errors.User.NotExisting")
}
if writeModel.ClientSecret == nil {
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-coi82n", "Errors.User.Machine.Secret.NotExisting")
}
return []eventstore.Command{
user.NewMachineSecretRemovedEvent(ctx, &a.Aggregate),
}, nil
}, nil
}
}
func (c *Commands) VerifyMachineSecret(ctx context.Context, userID string, resourceOwner string, secret string) (*domain.ObjectDetails, error) {
agg := user.NewAggregate(userID, resourceOwner)
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, prepareVerifyMachineSecret(agg, secret, c.userPasswordAlg))
if err != nil {
return nil, err
}
events, err := c.eventstore.Push(ctx, cmds...)
for _, cmd := range cmds {
if cmd.Type() == user.MachineSecretCheckFailedType {
logging.OnError(err).Error("could not push event MachineSecretCheckFailed")
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-3kjh", "Errors.User.Machine.Secret.Invalid")
}
}
if err != nil {
return nil, err
}
return &domain.ObjectDetails{
Sequence: events[len(events)-1].Sequence(),
EventDate: events[len(events)-1].CreationDate(),
ResourceOwner: events[len(events)-1].Aggregate().ResourceOwner,
}, nil
}
func prepareVerifyMachineSecret(a *user.Aggregate, secret string, algorithm crypto.HashAlgorithm) preparation.Validation {
return func() (_ preparation.CreateCommands, err error) {
if a.ResourceOwner == "" {
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-0qp2hus", "Errors.ResourceOwnerMissing")
}
if a.ID == "" {
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-bzosjs", "Errors.User.UserIDMissing")
}
return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
writeModel, err := getMachineWriteModel(ctx, a.ID, a.ResourceOwner, filter)
if err != nil {
return nil, err
}
if !isUserStateExists(writeModel.UserState) {
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-569sh2o", "Errors.User.NotExisting")
}
if writeModel.ClientSecret == nil {
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-x8910n", "Errors.User.Machine.Secret.NotExisting")
}
err = crypto.CompareHash(writeModel.ClientSecret, []byte(secret), algorithm)
if err == nil {
return []eventstore.Command{
user.NewMachineSecretCheckSucceededEvent(ctx, &a.Aggregate),
}, nil
}
return []eventstore.Command{
user.NewMachineSecretCheckFailedEvent(ctx, &a.Aggregate),
}, nil
}, nil
}
}

View File

@@ -0,0 +1,543 @@
package command
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
"github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/domain"
caos_errs "github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/eventstore/repository"
"github.com/zitadel/zitadel/internal/repository/user"
)
func TestCommandSide_GenerateMachineSecret(t *testing.T) {
type fields struct {
eventstore *eventstore.Eventstore
}
type args struct {
ctx context.Context
userID string
resourceOwner string
generator crypto.Generator
set *GenerateMachineSecret
}
type res struct {
want *domain.ObjectDetails
secret *GenerateMachineSecret
err func(error) bool
}
tests := []struct {
name string
fields fields
args args
res res
}{
{
name: "user invalid, invalid argument error userID",
fields: fields{
eventstore: eventstoreExpect(
t,
),
},
args: args{
ctx: context.Background(),
userID: "",
resourceOwner: "org1",
generator: GetMockSecretGenerator(t),
set: nil,
},
res: res{
err: caos_errs.IsErrorInvalidArgument,
},
},
{
name: "user invalid, invalid argument error resourceowner",
fields: fields{
eventstore: eventstoreExpect(
t,
),
},
args: args{
ctx: context.Background(),
userID: "user1",
resourceOwner: "",
generator: GetMockSecretGenerator(t),
set: nil,
},
res: res{
err: caos_errs.IsErrorInvalidArgument,
},
},
{
name: "user not existing, precondition error",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(),
),
},
args: args{
ctx: context.Background(),
userID: "user1",
resourceOwner: "org1",
generator: GetMockSecretGenerator(t),
set: nil,
},
res: res{
err: caos_errs.IsPreconditionFailed,
},
},
{
name: "add machine secret, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(
eventFromEventPusher(
user.NewMachineAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"user1",
"username",
"user",
false,
),
),
),
expectPush(
[]*repository.Event{
eventFromEventPusher(
user.NewMachineSecretSetEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("a"),
},
),
),
},
),
),
},
args: args{
ctx: context.Background(),
userID: "user1",
resourceOwner: "org1",
generator: GetMockSecretGenerator(t),
set: &GenerateMachineSecret{},
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
},
secret: &GenerateMachineSecret{
ClientID: "user1",
ClientSecret: "a",
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore,
}
got, err := r.GenerateMachineSecret(tt.args.ctx, tt.args.userID, tt.args.resourceOwner, tt.args.generator, tt.args.set)
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)
assert.Equal(t, tt.args.set.ClientID, tt.res.secret.ClientID)
assert.Equal(t, tt.args.set.ClientSecret, tt.res.secret.ClientSecret)
}
})
}
}
func TestCommandSide_RemoveMachineSecret(t *testing.T) {
type fields struct {
eventstore *eventstore.Eventstore
}
type args struct {
ctx context.Context
userID string
resourceOwner string
}
type res struct {
want *domain.ObjectDetails
err func(error) bool
}
tests := []struct {
name string
fields fields
args args
res res
}{
{
name: "user invalid, invalid argument error userID",
fields: fields{
eventstore: eventstoreExpect(
t,
),
},
args: args{
ctx: context.Background(),
userID: "",
resourceOwner: "org1",
},
res: res{
err: caos_errs.IsErrorInvalidArgument,
},
},
{
name: "user invalid, invalid argument error resourceowner",
fields: fields{
eventstore: eventstoreExpect(
t,
),
},
args: args{
ctx: context.Background(),
userID: "user1",
resourceOwner: "",
},
res: res{
err: caos_errs.IsErrorInvalidArgument,
},
},
{
name: "user not existing, precondition error",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(),
),
},
args: args{
ctx: context.Background(),
userID: "user1",
resourceOwner: "org1",
},
res: res{
err: caos_errs.IsPreconditionFailed,
},
},
{
name: "user existing without secret, precondition error",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(
eventFromEventPusher(
user.NewMachineAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"user1",
"username",
"user",
false,
),
),
),
),
},
args: args{
ctx: context.Background(),
userID: "user1",
resourceOwner: "org1",
},
res: res{
err: caos_errs.IsPreconditionFailed,
},
},
{
name: "remove machine secret, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(
eventFromEventPusher(
user.NewMachineAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"user1",
"username",
"user",
false,
),
),
eventFromEventPusher(
user.NewMachineSecretSetEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("a"),
},
),
),
),
expectPush(
[]*repository.Event{
eventFromEventPusher(
user.NewMachineSecretRemovedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
),
),
},
),
),
},
args: args{
ctx: context.Background(),
userID: "user1",
resourceOwner: "org1",
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore,
}
got, err := r.RemoveMachineSecret(tt.args.ctx, tt.args.userID, tt.args.resourceOwner)
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_VerifyMachineSecret(t *testing.T) {
type fields struct {
eventstore *eventstore.Eventstore
}
type args struct {
ctx context.Context
userID string
resourceOwner string
secret string
}
type res struct {
want *domain.ObjectDetails
err func(error) bool
}
tests := []struct {
name string
fields fields
args args
res res
}{
{
name: "user invalid, invalid argument error userID",
fields: fields{
eventstore: eventstoreExpect(
t,
),
},
args: args{
ctx: context.Background(),
userID: "",
resourceOwner: "org1",
},
res: res{
err: caos_errs.IsErrorInvalidArgument,
},
},
{
name: "user invalid, invalid argument error resourceowner",
fields: fields{
eventstore: eventstoreExpect(
t,
),
},
args: args{
ctx: context.Background(),
userID: "user1",
resourceOwner: "",
},
res: res{
err: caos_errs.IsErrorInvalidArgument,
},
},
{
name: "user not existing, precondition error",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(),
),
},
args: args{
ctx: context.Background(),
userID: "user1",
resourceOwner: "org1",
},
res: res{
err: caos_errs.IsPreconditionFailed,
},
},
{
name: "user existing without secret, precondition error",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(
eventFromEventPusher(
user.NewMachineAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"user1",
"username",
"user",
false,
),
),
),
),
},
args: args{
ctx: context.Background(),
userID: "user1",
resourceOwner: "org1",
},
res: res{
err: caos_errs.IsPreconditionFailed,
},
},
{
name: "verify machine secret, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(
eventFromEventPusher(
user.NewMachineAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"user1",
"username",
"user",
false,
),
),
eventFromEventPusher(
user.NewMachineSecretSetEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "bcrypt",
KeyID: "id",
Crypted: []byte("$2a$14$HxC7TAXMeowdqHdSBUfsjOUc0IGajYeApxdYl9lAYC0duZmSkgFia"),
},
),
),
),
expectPush(
[]*repository.Event{
eventFromEventPusher(
user.NewMachineSecretCheckSucceededEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
),
),
},
),
),
},
args: args{
ctx: context.Background(),
userID: "user1",
resourceOwner: "org1",
secret: "test",
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
},
},
},
{
name: "verify machine secret, failed",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(
eventFromEventPusher(
user.NewMachineAddedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
"user1",
"username",
"user",
false,
),
),
eventFromEventPusher(
user.NewMachineSecretSetEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "bcrypt",
KeyID: "id",
Crypted: []byte("$2a$14$HxC7TAXMeowdqHdSBUfsjOUc0IGajYeApxdYl9lAYC0duZmSkgFia"),
},
),
),
),
expectPush(
[]*repository.Event{
eventFromEventPusher(
user.NewMachineSecretCheckFailedEvent(context.Background(),
&user.NewAggregate("user1", "org1").Aggregate,
),
),
},
),
),
},
args: args{
ctx: context.Background(),
userID: "user1",
resourceOwner: "org1",
secret: "wrong",
},
res: res{
err: caos_errs.IsErrorInvalidArgument,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore,
userPasswordAlg: crypto.NewBCrypt(14),
}
got, err := r.VerifyMachineSecret(tt.args.ctx, tt.args.userID, tt.args.resourceOwner, tt.args.secret)
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)
}
})
}
}

View File

@@ -0,0 +1,14 @@
package domain
import (
"github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/errors"
)
func NewMachineClientSecret(generator crypto.Generator) (*crypto.CryptoValue, string, error) {
cryptoValue, stringSecret, err := crypto.NewCode(generator)
if err != nil {
return nil, "", errors.ThrowInternal(err, "MODEL-57cjsiw", "Errors.User.Machine.Secret.CouldNotGenerate")
}
return cryptoValue, stringSecret, nil
}

View File

@@ -20,18 +20,18 @@ var (
", members.user_id" +
", members.roles" +
", projections.login_names2.login_name" +
", projections.users6_humans.email" +
", projections.users6_humans.first_name" +
", projections.users6_humans.last_name" +
", projections.users6_humans.display_name" +
", projections.users6_machines.name" +
", projections.users6_humans.avatar_key" +
", projections.users7_humans.email" +
", projections.users7_humans.first_name" +
", projections.users7_humans.last_name" +
", projections.users7_humans.display_name" +
", projections.users7_machines.name" +
", projections.users7_humans.avatar_key" +
", COUNT(*) OVER () " +
"FROM projections.instance_members3 AS members " +
"LEFT JOIN projections.users6_humans " +
"ON members.user_id = projections.users6_humans.user_id AND members.instance_id = projections.users6_humans.instance_id " +
"LEFT JOIN projections.users6_machines " +
"ON members.user_id = projections.users6_machines.user_id AND members.instance_id = projections.users6_machines.instance_id " +
"LEFT JOIN projections.users7_humans " +
"ON members.user_id = projections.users7_humans.user_id AND members.instance_id = projections.users7_humans.instance_id " +
"LEFT JOIN projections.users7_machines " +
"ON members.user_id = projections.users7_machines.user_id AND members.instance_id = projections.users7_machines.instance_id " +
"LEFT JOIN projections.login_names2 " +
"ON members.user_id = projections.login_names2.user_id AND members.instance_id = projections.login_names2.instance_id " +
"WHERE projections.login_names2.is_primary = $1")

View File

@@ -20,20 +20,20 @@ var (
", members.user_id" +
", members.roles" +
", projections.login_names2.login_name" +
", projections.users6_humans.email" +
", projections.users6_humans.first_name" +
", projections.users6_humans.last_name" +
", projections.users6_humans.display_name" +
", projections.users6_machines.name" +
", projections.users6_humans.avatar_key" +
", projections.users7_humans.email" +
", projections.users7_humans.first_name" +
", projections.users7_humans.last_name" +
", projections.users7_humans.display_name" +
", projections.users7_machines.name" +
", projections.users7_humans.avatar_key" +
", COUNT(*) OVER () " +
"FROM projections.org_members3 AS members " +
"LEFT JOIN projections.users6_humans " +
"ON members.user_id = projections.users6_humans.user_id " +
"AND members.instance_id = projections.users6_humans.instance_id " +
"LEFT JOIN projections.users6_machines " +
"ON members.user_id = projections.users6_machines.user_id " +
"AND members.instance_id = projections.users6_machines.instance_id " +
"LEFT JOIN projections.users7_humans " +
"ON members.user_id = projections.users7_humans.user_id " +
"AND members.instance_id = projections.users7_humans.instance_id " +
"LEFT JOIN projections.users7_machines " +
"ON members.user_id = projections.users7_machines.user_id " +
"AND members.instance_id = projections.users7_machines.instance_id " +
"LEFT JOIN projections.login_names2 " +
"ON members.user_id = projections.login_names2.user_id " +
"AND members.instance_id = projections.login_names2.instance_id " +

View File

@@ -20,20 +20,20 @@ var (
", members.user_id" +
", members.roles" +
", projections.login_names2.login_name" +
", projections.users6_humans.email" +
", projections.users6_humans.first_name" +
", projections.users6_humans.last_name" +
", projections.users6_humans.display_name" +
", projections.users6_machines.name" +
", projections.users6_humans.avatar_key" +
", projections.users7_humans.email" +
", projections.users7_humans.first_name" +
", projections.users7_humans.last_name" +
", projections.users7_humans.display_name" +
", projections.users7_machines.name" +
", projections.users7_humans.avatar_key" +
", COUNT(*) OVER () " +
"FROM projections.project_grant_members3 AS members " +
"LEFT JOIN projections.users6_humans " +
"ON members.user_id = projections.users6_humans.user_id " +
"AND members.instance_id = projections.users6_humans.instance_id " +
"LEFT JOIN projections.users6_machines " +
"ON members.user_id = projections.users6_machines.user_id " +
"AND members.instance_id = projections.users6_machines.instance_id " +
"LEFT JOIN projections.users7_humans " +
"ON members.user_id = projections.users7_humans.user_id " +
"AND members.instance_id = projections.users7_humans.instance_id " +
"LEFT JOIN projections.users7_machines " +
"ON members.user_id = projections.users7_machines.user_id " +
"AND members.instance_id = projections.users7_machines.instance_id " +
"LEFT JOIN projections.login_names2 " +
"ON members.user_id = projections.login_names2.user_id " +
"AND members.instance_id = projections.login_names2.instance_id " +

View File

@@ -20,20 +20,20 @@ var (
", members.user_id" +
", members.roles" +
", projections.login_names2.login_name" +
", projections.users6_humans.email" +
", projections.users6_humans.first_name" +
", projections.users6_humans.last_name" +
", projections.users6_humans.display_name" +
", projections.users6_machines.name" +
", projections.users6_humans.avatar_key" +
", projections.users7_humans.email" +
", projections.users7_humans.first_name" +
", projections.users7_humans.last_name" +
", projections.users7_humans.display_name" +
", projections.users7_machines.name" +
", projections.users7_humans.avatar_key" +
", COUNT(*) OVER () " +
"FROM projections.project_members3 AS members " +
"LEFT JOIN projections.users6_humans " +
"ON members.user_id = projections.users6_humans.user_id " +
"AND members.instance_id = projections.users6_humans.instance_id " +
"LEFT JOIN projections.users6_machines " +
"ON members.user_id = projections.users6_machines.user_id " +
"AND members.instance_id = projections.users6_machines.instance_id " +
"LEFT JOIN projections.users7_humans " +
"ON members.user_id = projections.users7_humans.user_id " +
"AND members.instance_id = projections.users7_humans.instance_id " +
"LEFT JOIN projections.users7_machines " +
"ON members.user_id = projections.users7_machines.user_id " +
"AND members.instance_id = projections.users7_machines.instance_id " +
"LEFT JOIN projections.login_names2 " +
"ON members.user_id = projections.login_names2.user_id " +
"AND members.instance_id = projections.login_names2.instance_id " +

View File

@@ -19,7 +19,7 @@ type userProjection struct {
}
const (
UserTable = "projections.users6"
UserTable = "projections.users7"
UserHumanTable = UserTable + "_" + UserHumanSuffix
UserMachineTable = UserTable + "_" + UserMachineSuffix
UserNotifyTable = UserTable + "_" + UserNotifySuffix
@@ -62,6 +62,7 @@ const (
MachineUserInstanceIDCol = "instance_id"
MachineNameCol = "name"
MachineDescriptionCol = "description"
MachineHasSecretCol = "has_secret"
// notify
UserNotifySuffix = "notifications"
@@ -120,6 +121,7 @@ func newUserProjection(ctx context.Context, config crdb.StatementHandlerConfig)
crdb.NewColumn(MachineUserInstanceIDCol, crdb.ColumnTypeText),
crdb.NewColumn(MachineNameCol, crdb.ColumnTypeText),
crdb.NewColumn(MachineDescriptionCol, crdb.ColumnTypeText, crdb.Nullable()),
crdb.NewColumn(MachineHasSecretCol, crdb.ColumnTypeBool, crdb.Default(false)),
},
crdb.NewPrimaryKey(MachineUserInstanceIDCol, MachineUserIDCol),
UserMachineSuffix,
@@ -276,6 +278,14 @@ func (p *userProjection) reducers() []handler.AggregateReducer {
Event: user.HumanPasswordChangedType,
Reduce: p.reduceHumanPasswordChanged,
},
{
Event: user.MachineSecretSetType,
Reduce: p.reduceMachineSecretSet,
},
{
Event: user.MachineSecretRemovedType,
Reduce: p.reduceMachineSecretRemoved,
},
},
},
{
@@ -907,6 +917,67 @@ func (p *userProjection) reduceHumanPasswordChanged(event eventstore.Event) (*ha
), nil
}
func (p *userProjection) reduceMachineSecretSet(event eventstore.Event) (*handler.Statement, error) {
e, ok := event.(*user.MachineSecretSetEvent)
if !ok {
return nil, errors.ThrowInvalidArgumentf(nil, "HANDL-x0p1n1i", "reduce.wrong.event.type %s", user.MachineSecretSetType)
}
return crdb.NewMultiStatement(
e,
crdb.AddUpdateStatement(
[]handler.Column{
handler.NewCol(UserChangeDateCol, e.CreationDate()),
handler.NewCol(UserSequenceCol, e.Sequence()),
},
[]handler.Condition{
handler.NewCond(UserIDCol, e.Aggregate().ID),
handler.NewCond(UserInstanceIDCol, e.Aggregate().InstanceID),
},
),
crdb.AddUpdateStatement(
[]handler.Column{
handler.NewCol(MachineHasSecretCol, true),
},
[]handler.Condition{
handler.NewCond(MachineUserIDCol, e.Aggregate().ID),
handler.NewCond(MachineUserInstanceIDCol, e.Aggregate().InstanceID),
},
crdb.WithTableSuffix(UserMachineSuffix),
),
), nil
}
func (p *userProjection) reduceMachineSecretRemoved(event eventstore.Event) (*handler.Statement, error) {
e, ok := event.(*user.MachineSecretRemovedEvent)
if !ok {
return nil, errors.ThrowInvalidArgumentf(nil, "HANDL-x0p6n1i", "reduce.wrong.event.type %s", user.MachineSecretRemovedType)
}
return crdb.NewMultiStatement(
e,
crdb.AddUpdateStatement(
[]handler.Column{
handler.NewCol(UserChangeDateCol, e.CreationDate()),
handler.NewCol(UserSequenceCol, e.Sequence()),
},
[]handler.Condition{
handler.NewCond(UserIDCol, e.Aggregate().ID),
handler.NewCond(UserInstanceIDCol, e.Aggregate().InstanceID),
},
),
crdb.AddUpdateStatement(
[]handler.Column{
handler.NewCol(MachineHasSecretCol, false),
},
[]handler.Condition{
handler.NewCond(MachineUserIDCol, e.Aggregate().ID),
handler.NewCond(MachineUserInstanceIDCol, e.Aggregate().InstanceID),
},
crdb.WithTableSuffix(UserMachineSuffix),
),
), nil
}
func (p *userProjection) reduceMachineAdded(event eventstore.Event) (*handler.Statement, error) {
e, ok := event.(*user.MachineAddedEvent)
if !ok {

View File

@@ -51,7 +51,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "INSERT INTO projections.users6 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
expectedStmt: "INSERT INTO projections.users7 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
expectedArgs: []interface{}{
"agg-id",
anyArg{},
@@ -65,7 +65,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "INSERT INTO projections.users6_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)",
expectedStmt: "INSERT INTO projections.users7_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@@ -80,7 +80,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "INSERT INTO projections.users6_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
expectedStmt: "INSERT INTO projections.users7_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@@ -120,7 +120,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "INSERT INTO projections.users6 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
expectedStmt: "INSERT INTO projections.users7 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
expectedArgs: []interface{}{
"agg-id",
anyArg{},
@@ -134,7 +134,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "INSERT INTO projections.users6_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)",
expectedStmt: "INSERT INTO projections.users7_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@@ -149,7 +149,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "INSERT INTO projections.users6_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
expectedStmt: "INSERT INTO projections.users7_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@@ -184,7 +184,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "INSERT INTO projections.users6 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
expectedStmt: "INSERT INTO projections.users7 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
expectedArgs: []interface{}{
"agg-id",
anyArg{},
@@ -198,7 +198,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "INSERT INTO projections.users6_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)",
expectedStmt: "INSERT INTO projections.users7_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@@ -213,7 +213,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "INSERT INTO projections.users6_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
expectedStmt: "INSERT INTO projections.users7_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@@ -253,7 +253,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "INSERT INTO projections.users6 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
expectedStmt: "INSERT INTO projections.users7 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
expectedArgs: []interface{}{
"agg-id",
anyArg{},
@@ -267,7 +267,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "INSERT INTO projections.users6_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)",
expectedStmt: "INSERT INTO projections.users7_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@@ -282,7 +282,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "INSERT INTO projections.users6_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
expectedStmt: "INSERT INTO projections.users7_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@@ -322,7 +322,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "INSERT INTO projections.users6 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
expectedStmt: "INSERT INTO projections.users7 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
expectedArgs: []interface{}{
"agg-id",
anyArg{},
@@ -336,7 +336,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "INSERT INTO projections.users6_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)",
expectedStmt: "INSERT INTO projections.users7_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@@ -351,7 +351,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "INSERT INTO projections.users6_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
expectedStmt: "INSERT INTO projections.users7_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@@ -386,7 +386,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "INSERT INTO projections.users6 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
expectedStmt: "INSERT INTO projections.users7 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
expectedArgs: []interface{}{
"agg-id",
anyArg{},
@@ -400,7 +400,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "INSERT INTO projections.users6_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)",
expectedStmt: "INSERT INTO projections.users7_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@@ -415,7 +415,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "INSERT INTO projections.users6_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
expectedStmt: "INSERT INTO projections.users7_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@@ -445,7 +445,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users6 SET state = $1 WHERE (id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users7 SET state = $1 WHERE (id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
domain.UserStateInitial,
"agg-id",
@@ -473,7 +473,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users6 SET state = $1 WHERE (id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users7 SET state = $1 WHERE (id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
domain.UserStateInitial,
"agg-id",
@@ -501,7 +501,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users6 SET state = $1 WHERE (id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users7 SET state = $1 WHERE (id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
domain.UserStateActive,
"agg-id",
@@ -529,7 +529,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users6 SET state = $1 WHERE (id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users7 SET state = $1 WHERE (id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
domain.UserStateActive,
"agg-id",
@@ -557,7 +557,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users6 SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedStmt: "UPDATE projections.users7 SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedArgs: []interface{}{
anyArg{},
domain.UserStateLocked,
@@ -587,7 +587,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users6 SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedStmt: "UPDATE projections.users7 SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedArgs: []interface{}{
anyArg{},
domain.UserStateActive,
@@ -617,7 +617,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users6 SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedStmt: "UPDATE projections.users7 SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedArgs: []interface{}{
anyArg{},
domain.UserStateInactive,
@@ -647,7 +647,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users6 SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedStmt: "UPDATE projections.users7 SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedArgs: []interface{}{
anyArg{},
domain.UserStateActive,
@@ -677,7 +677,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "DELETE FROM projections.users6 WHERE (id = $1) AND (instance_id = $2)",
expectedStmt: "DELETE FROM projections.users7 WHERE (id = $1) AND (instance_id = $2)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@@ -706,7 +706,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users6 SET (change_date, username, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedStmt: "UPDATE projections.users7 SET (change_date, username, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedArgs: []interface{}{
anyArg{},
"username",
@@ -738,7 +738,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users6 SET (change_date, username, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedStmt: "UPDATE projections.users7 SET (change_date, username, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedArgs: []interface{}{
anyArg{},
"id@temporary.domain",
@@ -775,7 +775,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users6 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users7 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@@ -784,7 +784,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users6_humans SET (first_name, last_name, nick_name, display_name, preferred_language, gender) = ($1, $2, $3, $4, $5, $6) WHERE (user_id = $7) AND (instance_id = $8)",
expectedStmt: "UPDATE projections.users7_humans SET (first_name, last_name, nick_name, display_name, preferred_language, gender) = ($1, $2, $3, $4, $5, $6) WHERE (user_id = $7) AND (instance_id = $8)",
expectedArgs: []interface{}{
"first-name",
"last-name",
@@ -824,7 +824,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users6 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users7 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@@ -833,7 +833,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users6_humans SET (first_name, last_name, nick_name, display_name, preferred_language, gender) = ($1, $2, $3, $4, $5, $6) WHERE (user_id = $7) AND (instance_id = $8)",
expectedStmt: "UPDATE projections.users7_humans SET (first_name, last_name, nick_name, display_name, preferred_language, gender) = ($1, $2, $3, $4, $5, $6) WHERE (user_id = $7) AND (instance_id = $8)",
expectedArgs: []interface{}{
"first-name",
"last-name",
@@ -868,7 +868,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users6 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users7 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@@ -877,7 +877,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users6_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users7_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
"+41 00 000 00 00",
false,
@@ -886,7 +886,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users6_notifications SET last_phone = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users7_notifications SET last_phone = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
&sql.NullString{String: "+41 00 000 00 00", Valid: true},
"agg-id",
@@ -916,7 +916,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users6 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users7 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@@ -925,7 +925,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users6_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users7_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
"+41 00 000 00 00",
false,
@@ -934,7 +934,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users6_notifications SET last_phone = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users7_notifications SET last_phone = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
&sql.NullString{String: "+41 00 000 00 00", Valid: true},
"agg-id",
@@ -962,7 +962,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users6 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users7 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@@ -971,7 +971,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users6_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users7_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
nil,
nil,
@@ -980,7 +980,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users6_notifications SET (last_phone, verified_phone) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users7_notifications SET (last_phone, verified_phone) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
nil,
nil,
@@ -1009,7 +1009,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users6 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users7 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@@ -1018,7 +1018,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users6_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users7_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
nil,
nil,
@@ -1027,7 +1027,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users6_notifications SET (last_phone, verified_phone) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users7_notifications SET (last_phone, verified_phone) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
nil,
nil,
@@ -1056,7 +1056,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users6 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users7 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@@ -1065,7 +1065,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users6_humans SET is_phone_verified = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users7_humans SET is_phone_verified = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
true,
"agg-id",
@@ -1073,7 +1073,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users6_notifications SET verified_phone = last_phone WHERE (user_id = $1) AND (instance_id = $2)",
expectedStmt: "UPDATE projections.users7_notifications SET verified_phone = last_phone WHERE (user_id = $1) AND (instance_id = $2)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@@ -1100,7 +1100,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users6 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users7 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@@ -1109,7 +1109,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users6_humans SET is_phone_verified = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users7_humans SET is_phone_verified = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
true,
"agg-id",
@@ -1117,7 +1117,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users6_notifications SET verified_phone = last_phone WHERE (user_id = $1) AND (instance_id = $2)",
expectedStmt: "UPDATE projections.users7_notifications SET verified_phone = last_phone WHERE (user_id = $1) AND (instance_id = $2)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@@ -1146,7 +1146,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users6 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users7 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@@ -1155,7 +1155,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users6_humans SET (email, is_email_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users7_humans SET (email, is_email_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
"email@zitadel.com",
false,
@@ -1164,7 +1164,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users6_notifications SET last_email = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users7_notifications SET last_email = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
&sql.NullString{String: "email@zitadel.com", Valid: true},
"agg-id",
@@ -1194,7 +1194,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users6 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users7 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@@ -1203,7 +1203,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users6_humans SET (email, is_email_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users7_humans SET (email, is_email_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
"email@zitadel.com",
false,
@@ -1212,7 +1212,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users6_notifications SET last_email = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users7_notifications SET last_email = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
&sql.NullString{String: "email@zitadel.com", Valid: true},
"agg-id",
@@ -1240,7 +1240,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users6 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users7 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@@ -1249,7 +1249,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users6_humans SET is_email_verified = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users7_humans SET is_email_verified = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
true,
"agg-id",
@@ -1257,7 +1257,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users6_notifications SET verified_email = last_email WHERE (user_id = $1) AND (instance_id = $2)",
expectedStmt: "UPDATE projections.users7_notifications SET verified_email = last_email WHERE (user_id = $1) AND (instance_id = $2)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@@ -1284,7 +1284,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users6 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users7 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@@ -1293,7 +1293,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users6_humans SET is_email_verified = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users7_humans SET is_email_verified = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
true,
"agg-id",
@@ -1301,7 +1301,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users6_notifications SET verified_email = last_email WHERE (user_id = $1) AND (instance_id = $2)",
expectedStmt: "UPDATE projections.users7_notifications SET verified_email = last_email WHERE (user_id = $1) AND (instance_id = $2)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@@ -1330,7 +1330,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users6 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users7 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@@ -1339,7 +1339,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users6_humans SET avatar_key = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users7_humans SET avatar_key = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
"users/agg-id/avatar",
"agg-id",
@@ -1367,7 +1367,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users6 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users7 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@@ -1376,7 +1376,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users6_humans SET avatar_key = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users7_humans SET avatar_key = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
nil,
"agg-id",
@@ -1407,7 +1407,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "INSERT INTO projections.users6 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
expectedStmt: "INSERT INTO projections.users7 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
expectedArgs: []interface{}{
"agg-id",
anyArg{},
@@ -1421,7 +1421,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "INSERT INTO projections.users6_machines (user_id, instance_id, name, description) VALUES ($1, $2, $3, $4)",
expectedStmt: "INSERT INTO projections.users7_machines (user_id, instance_id, name, description) VALUES ($1, $2, $3, $4)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@@ -1454,7 +1454,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "INSERT INTO projections.users6 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
expectedStmt: "INSERT INTO projections.users7 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
expectedArgs: []interface{}{
"agg-id",
anyArg{},
@@ -1468,7 +1468,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "INSERT INTO projections.users6_machines (user_id, instance_id, name, description) VALUES ($1, $2, $3, $4)",
expectedStmt: "INSERT INTO projections.users7_machines (user_id, instance_id, name, description) VALUES ($1, $2, $3, $4)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@@ -1500,7 +1500,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users6 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users7 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@@ -1509,7 +1509,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users6_machines SET (name, description) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users7_machines SET (name, description) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
"machine-name",
"description",
@@ -1540,7 +1540,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users6 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users7 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@@ -1549,7 +1549,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users6_machines SET name = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users7_machines SET name = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
"machine-name",
"agg-id",
@@ -1579,7 +1579,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users6 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users7 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@@ -1588,7 +1588,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users6_machines SET description = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users7_machines SET description = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
"description",
"agg-id",
@@ -1618,6 +1618,82 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
},
{
name: "reduceMachineSecretSet",
args: args{
event: getEvent(testEvent(
repository.EventType(user.MachineSecretSetType),
user.AggregateType,
[]byte(`{
"client_secret": {}
}`),
), user.MachineSecretSetEventMapper),
},
reduce: (&userProjection{}).reduceMachineSecretSet,
want: wantReduce{
aggregateType: user.AggregateType,
sequence: 15,
previousSequence: 10,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users7 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
"agg-id",
"instance-id",
},
},
{
expectedStmt: "UPDATE projections.users7_machines SET has_secret = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
true,
"agg-id",
"instance-id",
},
},
},
},
},
},
{
name: "reduceMachineSecretSet",
args: args{
event: getEvent(testEvent(
repository.EventType(user.MachineSecretRemovedType),
user.AggregateType,
[]byte(`{}`),
), user.MachineSecretRemovedEventMapper),
},
reduce: (&userProjection{}).reduceMachineSecretRemoved,
want: wantReduce{
aggregateType: user.AggregateType,
sequence: 15,
previousSequence: 10,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users7 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
"agg-id",
"instance-id",
},
},
{
expectedStmt: "UPDATE projections.users7_machines SET has_secret = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
false,
"agg-id",
"instance-id",
},
},
},
},
},
},
{
name: "org reduceOwnerRemoved",
reduce: (&userProjection{}).reduceOwnerRemoved,
@@ -1635,7 +1711,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users6 SET (change_date, sequence, owner_removed) = ($1, $2, $3) WHERE (instance_id = $4) AND (resource_owner = $5)",
expectedStmt: "UPDATE projections.users7 SET (change_date, sequence, owner_removed) = ($1, $2, $3) WHERE (instance_id = $4) AND (resource_owner = $5)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@@ -1665,7 +1741,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "DELETE FROM projections.users6 WHERE (instance_id = $1)",
expectedStmt: "DELETE FROM projections.users7 WHERE (instance_id = $1)",
expectedArgs: []interface{}{
"agg-id",
},

View File

@@ -90,6 +90,7 @@ type Phone struct {
type Machine struct {
Name string
Description string
HasSecret bool
}
type NotifyUser struct {
@@ -277,6 +278,10 @@ var (
name: projection.MachineDescriptionCol,
table: machineTable,
}
MachineHasSecretCol = Column{
name: projection.MachineHasSecretCol,
table: machineTable,
}
)
var (
@@ -747,6 +752,7 @@ func prepareUserQuery() (sq.SelectBuilder, func(*sql.Row) (*User, error)) {
MachineUserIDCol.identifier(),
MachineNameCol.identifier(),
MachineDescriptionCol.identifier(),
MachineHasSecretCol.identifier(),
countColumn.identifier(),
).
From(userTable.identifier()).
@@ -782,6 +788,7 @@ func prepareUserQuery() (sq.SelectBuilder, func(*sql.Row) (*User, error)) {
machineID := sql.NullString{}
name := sql.NullString{}
description := sql.NullString{}
hasSecret := sql.NullBool{}
err := row.Scan(
&u.ID,
@@ -809,6 +816,7 @@ func prepareUserQuery() (sq.SelectBuilder, func(*sql.Row) (*User, error)) {
&machineID,
&name,
&description,
&hasSecret,
&count,
)
@@ -839,6 +847,7 @@ func prepareUserQuery() (sq.SelectBuilder, func(*sql.Row) (*User, error)) {
u.Machine = &Machine{
Name: name.String,
Description: description.String,
HasSecret: hasSecret.Bool,
}
}
return u, nil
@@ -1209,6 +1218,7 @@ func prepareUsersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Users, error)) {
MachineUserIDCol.identifier(),
MachineNameCol.identifier(),
MachineDescriptionCol.identifier(),
MachineHasSecretCol.identifier(),
countColumn.identifier()).
From(userTable.identifier()).
LeftJoin(join(HumanUserIDCol, UserIDCol)).
@@ -1246,6 +1256,7 @@ func prepareUsersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Users, error)) {
machineID := sql.NullString{}
name := sql.NullString{}
description := sql.NullString{}
hasSecret := sql.NullBool{}
err := rows.Scan(
&u.ID,
@@ -1273,6 +1284,7 @@ func prepareUsersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Users, error)) {
&machineID,
&name,
&description,
&hasSecret,
&count,
)
if err != nil {
@@ -1302,6 +1314,7 @@ func prepareUsersQuery() (sq.SelectBuilder, func(*sql.Rows) (*Users, error)) {
u.Machine = &Machine{
Name: name.String,
Description: description.String,
HasSecret: hasSecret.Bool,
}
}

View File

@@ -23,14 +23,14 @@ var (
", projections.user_grants3.roles" +
", projections.user_grants3.state" +
", projections.user_grants3.user_id" +
", projections.users6.username" +
", projections.users6.type" +
", projections.users6.resource_owner" +
", projections.users6_humans.first_name" +
", projections.users6_humans.last_name" +
", projections.users6_humans.email" +
", projections.users6_humans.display_name" +
", projections.users6_humans.avatar_key" +
", projections.users7.username" +
", projections.users7.type" +
", projections.users7.resource_owner" +
", projections.users7_humans.first_name" +
", projections.users7_humans.last_name" +
", projections.users7_humans.email" +
", projections.users7_humans.display_name" +
", projections.users7_humans.avatar_key" +
", projections.login_names2.login_name" +
", projections.user_grants3.resource_owner" +
", projections.orgs.name" +
@@ -38,8 +38,8 @@ var (
", projections.user_grants3.project_id" +
", projections.projects3.name" +
" FROM projections.user_grants3" +
" LEFT JOIN projections.users6 ON projections.user_grants3.user_id = projections.users6.id AND projections.user_grants3.instance_id = projections.users6.instance_id" +
" LEFT JOIN projections.users6_humans ON projections.user_grants3.user_id = projections.users6_humans.user_id AND projections.user_grants3.instance_id = projections.users6_humans.instance_id" +
" LEFT JOIN projections.users7 ON projections.user_grants3.user_id = projections.users7.id AND projections.user_grants3.instance_id = projections.users7.instance_id" +
" LEFT JOIN projections.users7_humans ON projections.user_grants3.user_id = projections.users7_humans.user_id AND projections.user_grants3.instance_id = projections.users7_humans.instance_id" +
" LEFT JOIN projections.orgs ON projections.user_grants3.resource_owner = projections.orgs.id AND projections.user_grants3.instance_id = projections.orgs.instance_id" +
" LEFT JOIN projections.projects3 ON projections.user_grants3.project_id = projections.projects3.id AND projections.user_grants3.instance_id = projections.projects3.instance_id" +
" LEFT JOIN projections.login_names2 ON projections.user_grants3.user_id = projections.login_names2.user_id AND projections.user_grants3.instance_id = projections.login_names2.instance_id" +
@@ -77,14 +77,14 @@ var (
", projections.user_grants3.roles" +
", projections.user_grants3.state" +
", projections.user_grants3.user_id" +
", projections.users6.username" +
", projections.users6.type" +
", projections.users6.resource_owner" +
", projections.users6_humans.first_name" +
", projections.users6_humans.last_name" +
", projections.users6_humans.email" +
", projections.users6_humans.display_name" +
", projections.users6_humans.avatar_key" +
", projections.users7.username" +
", projections.users7.type" +
", projections.users7.resource_owner" +
", projections.users7_humans.first_name" +
", projections.users7_humans.last_name" +
", projections.users7_humans.email" +
", projections.users7_humans.display_name" +
", projections.users7_humans.avatar_key" +
", projections.login_names2.login_name" +
", projections.user_grants3.resource_owner" +
", projections.orgs.name" +
@@ -93,8 +93,8 @@ var (
", projections.projects3.name" +
", COUNT(*) OVER ()" +
" FROM projections.user_grants3" +
" LEFT JOIN projections.users6 ON projections.user_grants3.user_id = projections.users6.id AND projections.user_grants3.instance_id = projections.users6.instance_id" +
" LEFT JOIN projections.users6_humans ON projections.user_grants3.user_id = projections.users6_humans.user_id AND projections.user_grants3.instance_id = projections.users6_humans.instance_id" +
" LEFT JOIN projections.users7 ON projections.user_grants3.user_id = projections.users7.id AND projections.user_grants3.instance_id = projections.users7.instance_id" +
" LEFT JOIN projections.users7_humans ON projections.user_grants3.user_id = projections.users7_humans.user_id AND projections.user_grants3.instance_id = projections.users7_humans.instance_id" +
" LEFT JOIN projections.orgs ON projections.user_grants3.resource_owner = projections.orgs.id AND projections.user_grants3.instance_id = projections.orgs.instance_id" +
" LEFT JOIN projections.projects3 ON projections.user_grants3.project_id = projections.projects3.id AND projections.user_grants3.instance_id = projections.projects3.instance_id" +
" LEFT JOIN projections.login_names2 ON projections.user_grants3.user_id = projections.login_names2.user_id AND projections.user_grants3.instance_id = projections.login_names2.instance_id" +

View File

@@ -23,41 +23,42 @@ var (
preferredLoginNameQuery = `SELECT preferred_login_name.user_id, preferred_login_name.login_name, preferred_login_name.instance_id, preferred_login_name.user_owner_removed, preferred_login_name.policy_owner_removed, preferred_login_name.domain_owner_removed` +
` FROM projections.login_names2 AS preferred_login_name` +
` WHERE preferred_login_name.is_primary = $1`
userQuery = `SELECT projections.users6.id,` +
` projections.users6.creation_date,` +
` projections.users6.change_date,` +
` projections.users6.resource_owner,` +
` projections.users6.sequence,` +
` projections.users6.state,` +
` projections.users6.type,` +
` projections.users6.username,` +
userQuery = `SELECT projections.users7.id,` +
` projections.users7.creation_date,` +
` projections.users7.change_date,` +
` projections.users7.resource_owner,` +
` projections.users7.sequence,` +
` projections.users7.state,` +
` projections.users7.type,` +
` projections.users7.username,` +
` login_names.loginnames,` +
` preferred_login_name.login_name,` +
` projections.users6_humans.user_id,` +
` projections.users6_humans.first_name,` +
` projections.users6_humans.last_name,` +
` projections.users6_humans.nick_name,` +
` projections.users6_humans.display_name,` +
` projections.users6_humans.preferred_language,` +
` projections.users6_humans.gender,` +
` projections.users6_humans.avatar_key,` +
` projections.users6_humans.email,` +
` projections.users6_humans.is_email_verified,` +
` projections.users6_humans.phone,` +
` projections.users6_humans.is_phone_verified,` +
` projections.users6_machines.user_id,` +
` projections.users6_machines.name,` +
` projections.users6_machines.description,` +
` projections.users7_humans.user_id,` +
` projections.users7_humans.first_name,` +
` projections.users7_humans.last_name,` +
` projections.users7_humans.nick_name,` +
` projections.users7_humans.display_name,` +
` projections.users7_humans.preferred_language,` +
` projections.users7_humans.gender,` +
` projections.users7_humans.avatar_key,` +
` projections.users7_humans.email,` +
` projections.users7_humans.is_email_verified,` +
` projections.users7_humans.phone,` +
` projections.users7_humans.is_phone_verified,` +
` projections.users7_machines.user_id,` +
` projections.users7_machines.name,` +
` projections.users7_machines.description,` +
` projections.users7_machines.has_secret,` +
` COUNT(*) OVER ()` +
` FROM projections.users6` +
` LEFT JOIN projections.users6_humans ON projections.users6.id = projections.users6_humans.user_id AND projections.users6.instance_id = projections.users6_humans.instance_id` +
` LEFT JOIN projections.users6_machines ON projections.users6.id = projections.users6_machines.user_id AND projections.users6.instance_id = projections.users6_machines.instance_id` +
` FROM projections.users7` +
` LEFT JOIN projections.users7_humans ON projections.users7.id = projections.users7_humans.user_id AND projections.users7.instance_id = projections.users7_humans.instance_id` +
` LEFT JOIN projections.users7_machines ON projections.users7.id = projections.users7_machines.user_id AND projections.users7.instance_id = projections.users7_machines.instance_id` +
` LEFT JOIN` +
` (` + loginNamesQuery + `) AS login_names` +
` ON login_names.user_id = projections.users6.id AND login_names.instance_id = projections.users6.instance_id` +
` ON login_names.user_id = projections.users7.id AND login_names.instance_id = projections.users7.instance_id` +
` LEFT JOIN` +
` (` + preferredLoginNameQuery + `) AS preferred_login_name` +
` ON preferred_login_name.user_id = projections.users6.id AND preferred_login_name.instance_id = projections.users6.instance_id`
` ON preferred_login_name.user_id = projections.users7.id AND preferred_login_name.instance_id = projections.users7.instance_id`
userCols = []string{
"id",
"creation_date",
@@ -86,23 +87,24 @@ var (
"user_id",
"name",
"description",
"has_secret",
"count",
}
profileQuery = `SELECT projections.users6.id,` +
` projections.users6.creation_date,` +
` projections.users6.change_date,` +
` projections.users6.resource_owner,` +
` projections.users6.sequence,` +
` projections.users6_humans.user_id,` +
` projections.users6_humans.first_name,` +
` projections.users6_humans.last_name,` +
` projections.users6_humans.nick_name,` +
` projections.users6_humans.display_name,` +
` projections.users6_humans.preferred_language,` +
` projections.users6_humans.gender,` +
` projections.users6_humans.avatar_key` +
` FROM projections.users6` +
` LEFT JOIN projections.users6_humans ON projections.users6.id = projections.users6_humans.user_id AND projections.users6.instance_id = projections.users6_humans.instance_id`
profileQuery = `SELECT projections.users7.id,` +
` projections.users7.creation_date,` +
` projections.users7.change_date,` +
` projections.users7.resource_owner,` +
` projections.users7.sequence,` +
` projections.users7_humans.user_id,` +
` projections.users7_humans.first_name,` +
` projections.users7_humans.last_name,` +
` projections.users7_humans.nick_name,` +
` projections.users7_humans.display_name,` +
` projections.users7_humans.preferred_language,` +
` projections.users7_humans.gender,` +
` projections.users7_humans.avatar_key` +
` FROM projections.users7` +
` LEFT JOIN projections.users7_humans ON projections.users7.id = projections.users7_humans.user_id AND projections.users7.instance_id = projections.users7_humans.instance_id`
profileCols = []string{
"id",
"creation_date",
@@ -118,16 +120,16 @@ var (
"gender",
"avatar_key",
}
emailQuery = `SELECT projections.users6.id,` +
` projections.users6.creation_date,` +
` projections.users6.change_date,` +
` projections.users6.resource_owner,` +
` projections.users6.sequence,` +
` projections.users6_humans.user_id,` +
` projections.users6_humans.email,` +
` projections.users6_humans.is_email_verified` +
` FROM projections.users6` +
` LEFT JOIN projections.users6_humans ON projections.users6.id = projections.users6_humans.user_id AND projections.users6.instance_id = projections.users6_humans.instance_id`
emailQuery = `SELECT projections.users7.id,` +
` projections.users7.creation_date,` +
` projections.users7.change_date,` +
` projections.users7.resource_owner,` +
` projections.users7.sequence,` +
` projections.users7_humans.user_id,` +
` projections.users7_humans.email,` +
` projections.users7_humans.is_email_verified` +
` FROM projections.users7` +
` LEFT JOIN projections.users7_humans ON projections.users7.id = projections.users7_humans.user_id AND projections.users7.instance_id = projections.users7_humans.instance_id`
emailCols = []string{
"id",
"creation_date",
@@ -138,16 +140,16 @@ var (
"email",
"is_email_verified",
}
phoneQuery = `SELECT projections.users6.id,` +
` projections.users6.creation_date,` +
` projections.users6.change_date,` +
` projections.users6.resource_owner,` +
` projections.users6.sequence,` +
` projections.users6_humans.user_id,` +
` projections.users6_humans.phone,` +
` projections.users6_humans.is_phone_verified` +
` FROM projections.users6` +
` LEFT JOIN projections.users6_humans ON projections.users6.id = projections.users6_humans.user_id AND projections.users6.instance_id = projections.users6_humans.instance_id`
phoneQuery = `SELECT projections.users7.id,` +
` projections.users7.creation_date,` +
` projections.users7.change_date,` +
` projections.users7.resource_owner,` +
` projections.users7.sequence,` +
` projections.users7_humans.user_id,` +
` projections.users7_humans.phone,` +
` projections.users7_humans.is_phone_verified` +
` FROM projections.users7` +
` LEFT JOIN projections.users7_humans ON projections.users7.id = projections.users7_humans.user_id AND projections.users7.instance_id = projections.users7_humans.instance_id`
phoneCols = []string{
"id",
"creation_date",
@@ -158,14 +160,14 @@ var (
"phone",
"is_phone_verified",
}
userUniqueQuery = `SELECT projections.users6.id,` +
` projections.users6.state,` +
` projections.users6.username,` +
` projections.users6_humans.user_id,` +
` projections.users6_humans.email,` +
` projections.users6_humans.is_email_verified` +
` FROM projections.users6` +
` LEFT JOIN projections.users6_humans ON projections.users6.id = projections.users6_humans.user_id AND projections.users6.instance_id = projections.users6_humans.instance_id`
userUniqueQuery = `SELECT projections.users7.id,` +
` projections.users7.state,` +
` projections.users7.username,` +
` projections.users7_humans.user_id,` +
` projections.users7_humans.email,` +
` projections.users7_humans.is_email_verified` +
` FROM projections.users7` +
` LEFT JOIN projections.users7_humans ON projections.users7.id = projections.users7_humans.user_id AND projections.users7.instance_id = projections.users7_humans.instance_id`
userUniqueCols = []string{
"id",
"state",
@@ -174,40 +176,40 @@ var (
"email",
"is_email_verified",
}
notifyUserQuery = `SELECT projections.users6.id,` +
` projections.users6.creation_date,` +
` projections.users6.change_date,` +
` projections.users6.resource_owner,` +
` projections.users6.sequence,` +
` projections.users6.state,` +
` projections.users6.type,` +
` projections.users6.username,` +
notifyUserQuery = `SELECT projections.users7.id,` +
` projections.users7.creation_date,` +
` projections.users7.change_date,` +
` projections.users7.resource_owner,` +
` projections.users7.sequence,` +
` projections.users7.state,` +
` projections.users7.type,` +
` projections.users7.username,` +
` login_names.loginnames,` +
` preferred_login_name.login_name,` +
` projections.users6_humans.user_id,` +
` projections.users6_humans.first_name,` +
` projections.users6_humans.last_name,` +
` projections.users6_humans.nick_name,` +
` projections.users6_humans.display_name,` +
` projections.users6_humans.preferred_language,` +
` projections.users6_humans.gender,` +
` projections.users6_humans.avatar_key,` +
` projections.users6_notifications.user_id,` +
` projections.users6_notifications.last_email,` +
` projections.users6_notifications.verified_email,` +
` projections.users6_notifications.last_phone,` +
` projections.users6_notifications.verified_phone,` +
` projections.users6_notifications.password_set,` +
` projections.users7_humans.user_id,` +
` projections.users7_humans.first_name,` +
` projections.users7_humans.last_name,` +
` projections.users7_humans.nick_name,` +
` projections.users7_humans.display_name,` +
` projections.users7_humans.preferred_language,` +
` projections.users7_humans.gender,` +
` projections.users7_humans.avatar_key,` +
` projections.users7_notifications.user_id,` +
` projections.users7_notifications.last_email,` +
` projections.users7_notifications.verified_email,` +
` projections.users7_notifications.last_phone,` +
` projections.users7_notifications.verified_phone,` +
` projections.users7_notifications.password_set,` +
` COUNT(*) OVER ()` +
` FROM projections.users6` +
` LEFT JOIN projections.users6_humans ON projections.users6.id = projections.users6_humans.user_id AND projections.users6.instance_id = projections.users6_humans.instance_id` +
` LEFT JOIN projections.users6_notifications ON projections.users6.id = projections.users6_notifications.user_id AND projections.users6.instance_id = projections.users6_notifications.instance_id` +
` FROM projections.users7` +
` LEFT JOIN projections.users7_humans ON projections.users7.id = projections.users7_humans.user_id AND projections.users7.instance_id = projections.users7_humans.instance_id` +
` LEFT JOIN projections.users7_notifications ON projections.users7.id = projections.users7_notifications.user_id AND projections.users7.instance_id = projections.users7_notifications.instance_id` +
` LEFT JOIN` +
` (` + loginNamesQuery + `) AS login_names` +
` ON login_names.user_id = projections.users6.id AND login_names.instance_id = projections.users6.instance_id` +
` ON login_names.user_id = projections.users7.id AND login_names.instance_id = projections.users7.instance_id` +
` LEFT JOIN` +
` (` + preferredLoginNameQuery + `) AS preferred_login_name` +
` ON preferred_login_name.user_id = projections.users6.id AND preferred_login_name.instance_id = projections.users6.instance_id`
` ON preferred_login_name.user_id = projections.users7.id AND preferred_login_name.instance_id = projections.users7.instance_id`
notifyUserCols = []string{
"id",
"creation_date",
@@ -237,41 +239,42 @@ var (
"password_set",
"count",
}
usersQuery = `SELECT projections.users6.id,` +
` projections.users6.creation_date,` +
` projections.users6.change_date,` +
` projections.users6.resource_owner,` +
` projections.users6.sequence,` +
` projections.users6.state,` +
` projections.users6.type,` +
` projections.users6.username,` +
usersQuery = `SELECT projections.users7.id,` +
` projections.users7.creation_date,` +
` projections.users7.change_date,` +
` projections.users7.resource_owner,` +
` projections.users7.sequence,` +
` projections.users7.state,` +
` projections.users7.type,` +
` projections.users7.username,` +
` login_names.loginnames,` +
` preferred_login_name.login_name,` +
` projections.users6_humans.user_id,` +
` projections.users6_humans.first_name,` +
` projections.users6_humans.last_name,` +
` projections.users6_humans.nick_name,` +
` projections.users6_humans.display_name,` +
` projections.users6_humans.preferred_language,` +
` projections.users6_humans.gender,` +
` projections.users6_humans.avatar_key,` +
` projections.users6_humans.email,` +
` projections.users6_humans.is_email_verified,` +
` projections.users6_humans.phone,` +
` projections.users6_humans.is_phone_verified,` +
` projections.users6_machines.user_id,` +
` projections.users6_machines.name,` +
` projections.users6_machines.description,` +
` projections.users7_humans.user_id,` +
` projections.users7_humans.first_name,` +
` projections.users7_humans.last_name,` +
` projections.users7_humans.nick_name,` +
` projections.users7_humans.display_name,` +
` projections.users7_humans.preferred_language,` +
` projections.users7_humans.gender,` +
` projections.users7_humans.avatar_key,` +
` projections.users7_humans.email,` +
` projections.users7_humans.is_email_verified,` +
` projections.users7_humans.phone,` +
` projections.users7_humans.is_phone_verified,` +
` projections.users7_machines.user_id,` +
` projections.users7_machines.name,` +
` projections.users7_machines.description,` +
` projections.users7_machines.has_secret,` +
` COUNT(*) OVER ()` +
` FROM projections.users6` +
` LEFT JOIN projections.users6_humans ON projections.users6.id = projections.users6_humans.user_id AND projections.users6.instance_id = projections.users6_humans.instance_id` +
` LEFT JOIN projections.users6_machines ON projections.users6.id = projections.users6_machines.user_id AND projections.users6.instance_id = projections.users6_machines.instance_id` +
` FROM projections.users7` +
` LEFT JOIN projections.users7_humans ON projections.users7.id = projections.users7_humans.user_id AND projections.users7.instance_id = projections.users7_humans.instance_id` +
` LEFT JOIN projections.users7_machines ON projections.users7.id = projections.users7_machines.user_id AND projections.users7.instance_id = projections.users7_machines.instance_id` +
` LEFT JOIN` +
` (` + loginNamesQuery + `) AS login_names` +
` ON login_names.user_id = projections.users6.id AND login_names.instance_id = projections.users6.instance_id` +
` ON login_names.user_id = projections.users7.id AND login_names.instance_id = projections.users7.instance_id` +
` LEFT JOIN` +
` (` + preferredLoginNameQuery + `) AS preferred_login_name` +
` ON preferred_login_name.user_id = projections.users6.id AND preferred_login_name.instance_id = projections.users6.instance_id`
` ON preferred_login_name.user_id = projections.users7.id AND preferred_login_name.instance_id = projections.users7.instance_id`
usersCols = []string{
"id",
"creation_date",
@@ -300,6 +303,7 @@ var (
"user_id",
"name",
"description",
"has_secret",
"count",
}
)
@@ -372,6 +376,7 @@ func Test_UserPrepares(t *testing.T) {
nil,
nil,
nil,
nil,
1,
},
),
@@ -439,6 +444,7 @@ func Test_UserPrepares(t *testing.T) {
"id",
"name",
"description",
true,
1,
},
),
@@ -457,6 +463,7 @@ func Test_UserPrepares(t *testing.T) {
Machine: &Machine{
Name: "name",
Description: "description",
HasSecret: true,
},
},
},
@@ -1036,6 +1043,7 @@ func Test_UserPrepares(t *testing.T) {
nil,
nil,
nil,
nil,
},
},
),
@@ -1111,6 +1119,7 @@ func Test_UserPrepares(t *testing.T) {
nil,
nil,
nil,
nil,
},
{
"id",
@@ -1140,6 +1149,7 @@ func Test_UserPrepares(t *testing.T) {
"id",
"name",
"description",
true,
},
},
),
@@ -1188,6 +1198,7 @@ func Test_UserPrepares(t *testing.T) {
Machine: &Machine{
Name: "name",
Description: "description",
HasSecret: true,
},
},
},

View File

@@ -114,5 +114,9 @@ func RegisterEventMappers(es *eventstore.Eventstore) {
RegisterFilterEventMapper(AggregateType, MachineKeyAddedEventType, MachineKeyAddedEventMapper).
RegisterFilterEventMapper(AggregateType, MachineKeyRemovedEventType, MachineKeyRemovedEventMapper).
RegisterFilterEventMapper(AggregateType, PersonalAccessTokenAddedType, PersonalAccessTokenAddedEventMapper).
RegisterFilterEventMapper(AggregateType, PersonalAccessTokenRemovedType, PersonalAccessTokenRemovedEventMapper)
RegisterFilterEventMapper(AggregateType, PersonalAccessTokenRemovedType, PersonalAccessTokenRemovedEventMapper).
RegisterFilterEventMapper(AggregateType, MachineSecretSetType, MachineSecretSetEventMapper).
RegisterFilterEventMapper(AggregateType, MachineSecretRemovedType, MachineSecretRemovedEventMapper).
RegisterFilterEventMapper(AggregateType, MachineSecretCheckSucceededType, MachineSecretCheckSucceededEventMapper).
RegisterFilterEventMapper(AggregateType, MachineSecretCheckFailedType, MachineSecretCheckFailedEventMapper)
}

View File

@@ -0,0 +1,171 @@
package user
import (
"context"
"encoding/json"
"github.com/zitadel/zitadel/internal/crypto"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/eventstore/repository"
)
const (
machineSecretPrefix = machineEventPrefix + "secret."
MachineSecretSetType = machineSecretPrefix + "set"
MachineSecretRemovedType = machineSecretPrefix + "removed"
MachineSecretCheckSucceededType = machineSecretPrefix + "check.succeeded"
MachineSecretCheckFailedType = machineSecretPrefix + "check.failed"
)
type MachineSecretSetEvent struct {
eventstore.BaseEvent `json:"-"`
ClientSecret *crypto.CryptoValue `json:"clientSecret,omitempty"`
}
func (e *MachineSecretSetEvent) Data() interface{} {
return e
}
func (e *MachineSecretSetEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
return nil
}
func NewMachineSecretSetEvent(
ctx context.Context,
aggregate *eventstore.Aggregate,
clientSecret *crypto.CryptoValue,
) *MachineSecretSetEvent {
return &MachineSecretSetEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
aggregate,
MachineSecretSetType,
),
ClientSecret: clientSecret,
}
}
func MachineSecretSetEventMapper(event *repository.Event) (eventstore.Event, error) {
credentialsSet := &MachineSecretSetEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}
err := json.Unmarshal(event.Data, credentialsSet)
if err != nil {
return nil, errors.ThrowInternal(err, "USER-lopbqu", "unable to unmarshal machine secret set")
}
return credentialsSet, nil
}
type MachineSecretRemovedEvent struct {
eventstore.BaseEvent `json:"-"`
}
func (e *MachineSecretRemovedEvent) Data() interface{} {
return e
}
func (e *MachineSecretRemovedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
return nil
}
func NewMachineSecretRemovedEvent(
ctx context.Context,
aggregate *eventstore.Aggregate,
) *MachineSecretRemovedEvent {
return &MachineSecretRemovedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
aggregate,
MachineSecretRemovedType,
),
}
}
func MachineSecretRemovedEventMapper(event *repository.Event) (eventstore.Event, error) {
credentialsRemoved := &MachineSecretRemovedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}
err := json.Unmarshal(event.Data, credentialsRemoved)
if err != nil {
return nil, errors.ThrowInternal(err, "USER-quox9j2", "unable to unmarshal machine secret removed")
}
return credentialsRemoved, nil
}
type MachineSecretCheckSucceededEvent struct {
eventstore.BaseEvent `json:"-"`
}
func (e *MachineSecretCheckSucceededEvent) Data() interface{} {
return e
}
func (e *MachineSecretCheckSucceededEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
return nil
}
func NewMachineSecretCheckSucceededEvent(
ctx context.Context,
aggregate *eventstore.Aggregate,
) *MachineSecretCheckSucceededEvent {
return &MachineSecretCheckSucceededEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
aggregate,
MachineSecretCheckSucceededType,
),
}
}
func MachineSecretCheckSucceededEventMapper(event *repository.Event) (eventstore.Event, error) {
check := &MachineSecretCheckSucceededEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}
err := json.Unmarshal(event.Data, check)
if err != nil {
return nil, errors.ThrowInternal(err, "USER-x002n1p", "unable to unmarshal machine secret check succeeded")
}
return check, nil
}
type MachineSecretCheckFailedEvent struct {
eventstore.BaseEvent `json:"-"`
}
func (e *MachineSecretCheckFailedEvent) Data() interface{} {
return e
}
func (e *MachineSecretCheckFailedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
return nil
}
func NewMachineSecretCheckFailedEvent(
ctx context.Context,
aggregate *eventstore.Aggregate,
) *MachineSecretCheckFailedEvent {
return &MachineSecretCheckFailedEvent{
BaseEvent: *eventstore.NewBaseEventForPush(
ctx,
aggregate,
MachineSecretCheckFailedType,
),
}
}
func MachineSecretCheckFailedEventMapper(event *repository.Event) (eventstore.Event, error) {
check := &MachineSecretCheckFailedEvent{
BaseEvent: *eventstore.BaseEventFromRepo(event),
}
err := json.Unmarshal(event.Data, check)
if err != nil {
return nil, errors.ThrowInternal(err, "USER-x7901b1l", "unable to unmarshal machine secret check failed")
}
return check, nil
}

View File

@@ -87,6 +87,10 @@ Errors:
Key:
NotFound: Maschinen Schlüssel nicht gefunden
AlreadyExisting: Machine Schlüssel exisiert bereits
Secret:
NotExisting: Secret existiert nicht
Invalid: Secret ist ungültig
CouldNotGenerate: Secret konnte nicht generiert werden
PAT:
NotFound: Persönliches Access Token nicht gefunden
NotHuman: Der Benutzer muss eine Person sein
@@ -475,8 +479,14 @@ EventTypes:
added: Technischer Benutzer hinzugefügt
changed: Technischer Benutzer geändert
key:
added: Key added
removed: Key removed
added: Key hinzugefügt
removed: Key entfernt
secret:
set: Secret gesetzt
removed: Secret entfernt
check:
succeeded: Secret Überprüfung erfolgreich
failed: Secret Überprüfung fehlgeschlagen
human:
added: Benutzer hinzugefügt
selfregistered: Benutzer hat sich selbst registriert

View File

@@ -87,6 +87,10 @@ Errors:
Key:
NotFound: Machine key not found
AlreadyExisting: Machine key already existing
Secret:
NotExisting: Secret doesn't exist
Invalid: Secret is invalid
CouldNotGenerate: Secret could not be generated
PAT:
NotFound: Personal Access Token not found
NotHuman: The User must be personal
@@ -477,6 +481,12 @@ EventTypes:
key:
added: Key added
removed: Key removed
secret:
set: Secret set
removed: Secret removed
check:
succeeded: Secret check succeeded
failed: Secret check failed
human:
added: Person added
selfregistered: Person registered himself

View File

@@ -87,6 +87,10 @@ Errors:
Key:
NotFound: Clé de la machine non trouvée
AlreadyExisting: Clé de la machine déjà existante
Secret:
NotExisting: Secret n'existe pas
Invalid: Secret n'est pas valide
CouldNotGenerate: Secret n'a pas pu être généré
PAT:
NotFound: Token d'accès personnel non trouvé
NotHuman: L'utilisateur doit être personnel
@@ -475,6 +479,12 @@ EventTypes:
key:
added: Clé ajoutée
removed: Clé supprimée
secret:
set: Secret défini
removed: Secret supprimée
check:
succeeded: La vérification de Secret réussie
failed: La vérification de Secret a échoué
human:
added: Personne ajoutée
selfregistered: La personne s'est enregistrée elle-même

View File

@@ -87,6 +87,10 @@ Errors:
Key:
NotFound: Chiave macchina non trovato
AlreadyExisting: Chiave macchina già esistente
Secret:
NotExisting: Secret non esiste
Invalid: Secret non è valido
CouldNotGenerate: Non è stato possibile generare il Secret
PAT:
NotFound: Personal Access Token non trovato
NotHuman: L'utente deve essere personale
@@ -475,6 +479,12 @@ EventTypes:
key:
added: Chiave aggiunta
removed: Chiave rimossa
secret:
set: Secret set
removed: Secret rimosso
check:
succeeded: Controllo della Secret riuscito
failed: Controllo della Secret fallito
human:
added: Persona aggiunta
selfregistered: Persona registrata

View File

@@ -87,6 +87,10 @@ Errors:
Key:
NotFound: 未找到机器密钥
AlreadyExisting: 已有的机器钥匙
Secret:
NotExisting: 秘密并不存在
Invalid: 秘密是无效的
CouldNotGenerate: 无法生成秘密
PAT:
NotFound: 未找到个人访问令牌
NotHuman: 用户必须是个人
@@ -465,6 +469,12 @@ EventTypes:
key:
added: 添加服务用户 Key
removed: 删除服务用户 Key
secret:
set: 秘密套装
removed: 秘密删除
check:
succeeded: 成功的秘密控制
failed: 秘密控制失败
human:
added: 添加用户
selfregistered: 自注册用户