mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-13 14:55:28 +00:00
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:
@@ -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 {
|
||||
|
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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) }()
|
||||
|
120
internal/api/oidc/client_credentials.go
Normal file
120
internal/api/oidc/client_credentials.go
Normal 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
|
||||
}
|
@@ -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()
|
||||
}
|
||||
|
||||
|
171
internal/command/user_machine_secret.go
Normal file
171
internal/command/user_machine_secret.go
Normal 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
|
||||
}
|
||||
}
|
543
internal/command/user_machine_secret_test.go
Normal file
543
internal/command/user_machine_secret_test.go
Normal 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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
14
internal/domain/machine_secret.go
Normal file
14
internal/domain/machine_secret.go
Normal 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
|
||||
}
|
@@ -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")
|
||||
|
@@ -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 " +
|
||||
|
@@ -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 " +
|
||||
|
@@ -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 " +
|
||||
|
@@ -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 {
|
||||
|
@@ -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",
|
||||
},
|
||||
|
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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" +
|
||||
|
@@ -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,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@@ -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)
|
||||
}
|
||||
|
171
internal/repository/user/machine_secret.go
Normal file
171
internal/repository/user/machine_secret.go
Normal 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
|
||||
}
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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: 自注册用户
|
||||
|
Reference in New Issue
Block a user