2022-01-19 13:49:50 +00:00
package projection
import (
"testing"
2022-04-26 23:01:45 +00:00
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/eventstore/handler"
"github.com/zitadel/zitadel/internal/eventstore/repository"
2022-10-20 12:36:52 +00:00
"github.com/zitadel/zitadel/internal/repository/instance"
2022-11-30 16:01:17 +00:00
"github.com/zitadel/zitadel/internal/repository/org"
2022-04-26 23:01:45 +00:00
"github.com/zitadel/zitadel/internal/repository/user"
2022-01-19 13:49:50 +00:00
)
func TestUserAuthMethodProjection_reduces ( t * testing . T ) {
type args struct {
event func ( t * testing . T ) eventstore . Event
}
tests := [ ] struct {
name string
args args
reduce func ( event eventstore . Event ) ( * handler . Statement , error )
want wantReduce
} {
{
name : "reduceAddedPasswordless" ,
args : args {
event : getEvent ( testEvent (
repository . EventType ( user . HumanPasswordlessTokenAddedType ) ,
user . AggregateType ,
[ ] byte ( ` {
"webAuthNTokenId" : "token-id"
} ` ) ,
) , user . HumanPasswordlessAddedEventMapper ) ,
} ,
2022-06-14 05:51:00 +00:00
reduce : ( & userAuthMethodProjection { } ) . reduceInitAuthMethod ,
2022-01-19 13:49:50 +00:00
want : wantReduce {
aggregateType : user . AggregateType ,
sequence : 15 ,
previousSequence : 10 ,
executer : & testExecuter {
executions : [ ] execution {
{
2022-11-30 16:01:17 +00:00
expectedStmt : "INSERT INTO projections.user_auth_methods4 (token_id, creation_date, change_date, resource_owner, instance_id, user_id, sequence, state, method_type, name) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) ON CONFLICT (instance_id, user_id, method_type, token_id) DO UPDATE SET (creation_date, change_date, resource_owner, sequence, state, name) = (EXCLUDED.creation_date, EXCLUDED.change_date, EXCLUDED.resource_owner, EXCLUDED.sequence, EXCLUDED.state, EXCLUDED.name)" ,
2022-01-19 13:49:50 +00:00
expectedArgs : [ ] interface { } {
"token-id" ,
anyArg { } ,
anyArg { } ,
"ro-id" ,
2022-03-23 08:02:39 +00:00
"instance-id" ,
2022-01-19 13:49:50 +00:00
"agg-id" ,
uint64 ( 15 ) ,
domain . MFAStateNotReady ,
domain . UserAuthMethodTypePasswordless ,
"" ,
} ,
} ,
} ,
} ,
} ,
} ,
{
name : "reduceAddedU2F" ,
args : args {
event : getEvent ( testEvent (
repository . EventType ( user . HumanU2FTokenAddedType ) ,
user . AggregateType ,
[ ] byte ( ` {
"webAuthNTokenId" : "token-id"
} ` ) ,
) , user . HumanU2FAddedEventMapper ) ,
} ,
2022-06-14 05:51:00 +00:00
reduce : ( & userAuthMethodProjection { } ) . reduceInitAuthMethod ,
2022-01-19 13:49:50 +00:00
want : wantReduce {
aggregateType : user . AggregateType ,
sequence : 15 ,
previousSequence : 10 ,
executer : & testExecuter {
executions : [ ] execution {
{
2022-11-30 16:01:17 +00:00
expectedStmt : "INSERT INTO projections.user_auth_methods4 (token_id, creation_date, change_date, resource_owner, instance_id, user_id, sequence, state, method_type, name) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) ON CONFLICT (instance_id, user_id, method_type, token_id) DO UPDATE SET (creation_date, change_date, resource_owner, sequence, state, name) = (EXCLUDED.creation_date, EXCLUDED.change_date, EXCLUDED.resource_owner, EXCLUDED.sequence, EXCLUDED.state, EXCLUDED.name)" ,
2022-01-19 13:49:50 +00:00
expectedArgs : [ ] interface { } {
"token-id" ,
anyArg { } ,
anyArg { } ,
"ro-id" ,
2022-03-23 08:02:39 +00:00
"instance-id" ,
2022-01-19 13:49:50 +00:00
"agg-id" ,
uint64 ( 15 ) ,
domain . MFAStateNotReady ,
domain . UserAuthMethodTypeU2F ,
"" ,
} ,
} ,
} ,
} ,
} ,
} ,
{
2023-08-02 16:57:53 +00:00
name : "reduceAddedTOTP" ,
2022-01-19 13:49:50 +00:00
args : args {
event : getEvent ( testEvent (
repository . EventType ( user . HumanMFAOTPAddedType ) ,
user . AggregateType ,
[ ] byte ( ` {
} ` ) ,
) , user . HumanOTPAddedEventMapper ) ,
} ,
2022-06-14 05:51:00 +00:00
reduce : ( & userAuthMethodProjection { } ) . reduceInitAuthMethod ,
2022-01-19 13:49:50 +00:00
want : wantReduce {
aggregateType : user . AggregateType ,
sequence : 15 ,
previousSequence : 10 ,
executer : & testExecuter {
executions : [ ] execution {
{
2022-11-30 16:01:17 +00:00
expectedStmt : "INSERT INTO projections.user_auth_methods4 (token_id, creation_date, change_date, resource_owner, instance_id, user_id, sequence, state, method_type, name) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) ON CONFLICT (instance_id, user_id, method_type, token_id) DO UPDATE SET (creation_date, change_date, resource_owner, sequence, state, name) = (EXCLUDED.creation_date, EXCLUDED.change_date, EXCLUDED.resource_owner, EXCLUDED.sequence, EXCLUDED.state, EXCLUDED.name)" ,
2022-01-19 13:49:50 +00:00
expectedArgs : [ ] interface { } {
"" ,
anyArg { } ,
anyArg { } ,
"ro-id" ,
2022-03-23 08:02:39 +00:00
"instance-id" ,
2022-01-19 13:49:50 +00:00
"agg-id" ,
uint64 ( 15 ) ,
domain . MFAStateNotReady ,
2023-08-02 16:57:53 +00:00
domain . UserAuthMethodTypeTOTP ,
2022-01-19 13:49:50 +00:00
"" ,
} ,
} ,
} ,
} ,
} ,
} ,
{
name : "reduceVerifiedPasswordless" ,
args : args {
event : getEvent ( testEvent (
repository . EventType ( user . HumanPasswordlessTokenVerifiedType ) ,
user . AggregateType ,
[ ] byte ( ` {
"webAuthNTokenId" : "token-id" ,
"webAuthNTokenName" : "name"
} ` ) ,
) , user . HumanPasswordlessVerifiedEventMapper ) ,
} ,
2022-06-14 05:51:00 +00:00
reduce : ( & userAuthMethodProjection { } ) . reduceActivateEvent ,
2022-01-19 13:49:50 +00:00
want : wantReduce {
aggregateType : user . AggregateType ,
sequence : 15 ,
previousSequence : 10 ,
executer : & testExecuter {
executions : [ ] execution {
{
2022-11-30 16:01:17 +00:00
expectedStmt : "UPDATE projections.user_auth_methods4 SET (change_date, sequence, name, state) = ($1, $2, $3, $4) WHERE (user_id = $5) AND (method_type = $6) AND (resource_owner = $7) AND (token_id = $8) AND (instance_id = $9)" ,
2022-01-19 13:49:50 +00:00
expectedArgs : [ ] interface { } {
anyArg { } ,
uint64 ( 15 ) ,
"name" ,
domain . MFAStateReady ,
"agg-id" ,
domain . UserAuthMethodTypePasswordless ,
"ro-id" ,
"token-id" ,
2022-11-10 10:59:33 +00:00
"instance-id" ,
2022-01-19 13:49:50 +00:00
} ,
} ,
} ,
} ,
} ,
} ,
{
name : "reduceVerifiedU2F" ,
args : args {
event : getEvent ( testEvent (
repository . EventType ( user . HumanU2FTokenVerifiedType ) ,
user . AggregateType ,
[ ] byte ( ` {
"webAuthNTokenId" : "token-id" ,
"webAuthNTokenName" : "name"
} ` ) ,
) , user . HumanU2FVerifiedEventMapper ) ,
} ,
2022-06-14 05:51:00 +00:00
reduce : ( & userAuthMethodProjection { } ) . reduceActivateEvent ,
2022-01-19 13:49:50 +00:00
want : wantReduce {
aggregateType : user . AggregateType ,
sequence : 15 ,
previousSequence : 10 ,
executer : & testExecuter {
executions : [ ] execution {
{
2022-11-30 16:01:17 +00:00
expectedStmt : "UPDATE projections.user_auth_methods4 SET (change_date, sequence, name, state) = ($1, $2, $3, $4) WHERE (user_id = $5) AND (method_type = $6) AND (resource_owner = $7) AND (token_id = $8) AND (instance_id = $9)" ,
2022-01-19 13:49:50 +00:00
expectedArgs : [ ] interface { } {
anyArg { } ,
uint64 ( 15 ) ,
"name" ,
domain . MFAStateReady ,
"agg-id" ,
domain . UserAuthMethodTypeU2F ,
"ro-id" ,
"token-id" ,
2022-11-10 10:59:33 +00:00
"instance-id" ,
2022-01-19 13:49:50 +00:00
} ,
} ,
} ,
} ,
} ,
} ,
{
2023-08-02 16:57:53 +00:00
name : "reduceVerifiedTOTP" ,
2022-01-19 13:49:50 +00:00
args : args {
event : getEvent ( testEvent (
repository . EventType ( user . HumanMFAOTPVerifiedType ) ,
user . AggregateType ,
[ ] byte ( ` {
} ` ) ,
) , user . HumanOTPVerifiedEventMapper ) ,
} ,
2022-06-14 05:51:00 +00:00
reduce : ( & userAuthMethodProjection { } ) . reduceActivateEvent ,
2022-01-19 13:49:50 +00:00
want : wantReduce {
aggregateType : user . AggregateType ,
sequence : 15 ,
previousSequence : 10 ,
executer : & testExecuter {
executions : [ ] execution {
{
2022-11-30 16:01:17 +00:00
expectedStmt : "UPDATE projections.user_auth_methods4 SET (change_date, sequence, name, state) = ($1, $2, $3, $4) WHERE (user_id = $5) AND (method_type = $6) AND (resource_owner = $7) AND (token_id = $8) AND (instance_id = $9)" ,
2022-01-19 13:49:50 +00:00
expectedArgs : [ ] interface { } {
anyArg { } ,
uint64 ( 15 ) ,
"" ,
domain . MFAStateReady ,
"agg-id" ,
2023-08-02 16:57:53 +00:00
domain . UserAuthMethodTypeTOTP ,
2022-01-19 13:49:50 +00:00
"ro-id" ,
"" ,
2022-11-10 10:59:33 +00:00
"instance-id" ,
2022-01-19 13:49:50 +00:00
} ,
} ,
} ,
} ,
} ,
} ,
2023-08-02 16:57:53 +00:00
{
name : "reduceAddedOTPSMS" ,
args : args {
event : getEvent ( testEvent (
repository . EventType ( user . HumanOTPSMSAddedType ) ,
user . AggregateType ,
nil ,
) , eventstore . GenericEventMapper [ user . HumanOTPSMSAddedEvent ] ) ,
} ,
reduce : ( & userAuthMethodProjection { } ) . reduceAddAuthMethod ,
want : wantReduce {
aggregateType : user . AggregateType ,
sequence : 15 ,
previousSequence : 10 ,
executer : & testExecuter {
executions : [ ] execution {
{
expectedStmt : "INSERT INTO projections.user_auth_methods4 (token_id, creation_date, change_date, resource_owner, instance_id, user_id, sequence, state, method_type, name) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)" ,
expectedArgs : [ ] interface { } {
"" ,
anyArg { } ,
anyArg { } ,
"ro-id" ,
"instance-id" ,
"agg-id" ,
uint64 ( 15 ) ,
domain . MFAStateReady ,
domain . UserAuthMethodTypeOTPSMS ,
"" ,
} ,
} ,
} ,
} ,
} ,
} ,
{
name : "reduceAddedOTPEmail" ,
args : args {
event : getEvent ( testEvent (
repository . EventType ( user . HumanOTPEmailAddedType ) ,
user . AggregateType ,
nil ,
) , eventstore . GenericEventMapper [ user . HumanOTPEmailAddedEvent ] ) ,
} ,
reduce : ( & userAuthMethodProjection { } ) . reduceAddAuthMethod ,
want : wantReduce {
aggregateType : user . AggregateType ,
sequence : 15 ,
previousSequence : 10 ,
executer : & testExecuter {
executions : [ ] execution {
{
expectedStmt : "INSERT INTO projections.user_auth_methods4 (token_id, creation_date, change_date, resource_owner, instance_id, user_id, sequence, state, method_type, name) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)" ,
expectedArgs : [ ] interface { } {
"" ,
anyArg { } ,
anyArg { } ,
"ro-id" ,
"instance-id" ,
"agg-id" ,
uint64 ( 15 ) ,
domain . MFAStateReady ,
domain . UserAuthMethodTypeOTPEmail ,
"" ,
} ,
} ,
} ,
} ,
} ,
} ,
{
name : "reduceRemoveOTPPasswordless" ,
args : args {
event : getEvent ( testEvent (
repository . EventType ( user . HumanPasswordlessTokenRemovedType ) ,
user . AggregateType ,
[ ] byte ( ` {
"webAuthNTokenId" : "token-id"
} ` ) ,
) , user . HumanPasswordlessRemovedEventMapper ) ,
} ,
reduce : ( & userAuthMethodProjection { } ) . reduceRemoveAuthMethod ,
want : wantReduce {
aggregateType : user . AggregateType ,
sequence : 15 ,
previousSequence : 10 ,
executer : & testExecuter {
executions : [ ] execution {
{
expectedStmt : "DELETE FROM projections.user_auth_methods4 WHERE (user_id = $1) AND (method_type = $2) AND (resource_owner = $3) AND (instance_id = $4) AND (token_id = $5)" ,
expectedArgs : [ ] interface { } {
"agg-id" ,
domain . UserAuthMethodTypePasswordless ,
"ro-id" ,
"instance-id" ,
"token-id" ,
} ,
} ,
} ,
} ,
} ,
} ,
{
name : "reduceRemoveOTPU2F" ,
args : args {
event : getEvent ( testEvent (
repository . EventType ( user . HumanU2FTokenRemovedType ) ,
user . AggregateType ,
[ ] byte ( ` {
"webAuthNTokenId" : "token-id"
} ` ) ,
) , user . HumanU2FRemovedEventMapper ) ,
} ,
reduce : ( & userAuthMethodProjection { } ) . reduceRemoveAuthMethod ,
want : wantReduce {
aggregateType : user . AggregateType ,
sequence : 15 ,
previousSequence : 10 ,
executer : & testExecuter {
executions : [ ] execution {
{
expectedStmt : "DELETE FROM projections.user_auth_methods4 WHERE (user_id = $1) AND (method_type = $2) AND (resource_owner = $3) AND (instance_id = $4) AND (token_id = $5)" ,
expectedArgs : [ ] interface { } {
"agg-id" ,
domain . UserAuthMethodTypeU2F ,
"ro-id" ,
"instance-id" ,
"token-id" ,
} ,
} ,
} ,
} ,
} ,
} ,
{
name : "reduceRemoveTOTP" ,
args : args {
event : getEvent ( testEvent (
repository . EventType ( user . HumanMFAOTPRemovedType ) ,
user . AggregateType ,
nil ,
) , user . HumanOTPRemovedEventMapper ) ,
} ,
reduce : ( & userAuthMethodProjection { } ) . reduceRemoveAuthMethod ,
want : wantReduce {
aggregateType : user . AggregateType ,
sequence : 15 ,
previousSequence : 10 ,
executer : & testExecuter {
executions : [ ] execution {
{
expectedStmt : "DELETE FROM projections.user_auth_methods4 WHERE (user_id = $1) AND (method_type = $2) AND (resource_owner = $3) AND (instance_id = $4)" ,
expectedArgs : [ ] interface { } {
"agg-id" ,
domain . UserAuthMethodTypeTOTP ,
"ro-id" ,
"instance-id" ,
} ,
} ,
} ,
} ,
} ,
} ,
{
name : "reduceRemoveOTPSMS" ,
args : args {
event : getEvent ( testEvent (
repository . EventType ( user . HumanOTPSMSRemovedType ) ,
user . AggregateType ,
nil ,
) , eventstore . GenericEventMapper [ user . HumanOTPSMSRemovedEvent ] ) ,
} ,
reduce : ( & userAuthMethodProjection { } ) . reduceRemoveAuthMethod ,
want : wantReduce {
aggregateType : user . AggregateType ,
sequence : 15 ,
previousSequence : 10 ,
executer : & testExecuter {
executions : [ ] execution {
{
expectedStmt : "DELETE FROM projections.user_auth_methods4 WHERE (user_id = $1) AND (method_type = $2) AND (resource_owner = $3) AND (instance_id = $4)" ,
expectedArgs : [ ] interface { } {
"agg-id" ,
domain . UserAuthMethodTypeOTPSMS ,
"ro-id" ,
"instance-id" ,
} ,
} ,
} ,
} ,
} ,
} ,
{
name : "reduceRemovePhone" ,
args : args {
event : getEvent ( testEvent (
repository . EventType ( user . HumanPhoneRemovedType ) ,
user . AggregateType ,
nil ,
) , user . HumanPhoneRemovedEventMapper ) ,
} ,
reduce : ( & userAuthMethodProjection { } ) . reduceRemoveAuthMethod ,
want : wantReduce {
aggregateType : user . AggregateType ,
sequence : 15 ,
previousSequence : 10 ,
executer : & testExecuter {
executions : [ ] execution {
{
expectedStmt : "DELETE FROM projections.user_auth_methods4 WHERE (user_id = $1) AND (method_type = $2) AND (resource_owner = $3) AND (instance_id = $4)" ,
expectedArgs : [ ] interface { } {
"agg-id" ,
domain . UserAuthMethodTypeOTPSMS ,
"ro-id" ,
"instance-id" ,
} ,
} ,
} ,
} ,
} ,
} ,
{
name : "reduceRemoveOTPEmail" ,
args : args {
event : getEvent ( testEvent (
repository . EventType ( user . HumanOTPEmailRemovedType ) ,
user . AggregateType ,
nil ,
) , eventstore . GenericEventMapper [ user . HumanOTPEmailRemovedEvent ] ) ,
} ,
reduce : ( & userAuthMethodProjection { } ) . reduceRemoveAuthMethod ,
want : wantReduce {
aggregateType : user . AggregateType ,
sequence : 15 ,
previousSequence : 10 ,
executer : & testExecuter {
executions : [ ] execution {
{
expectedStmt : "DELETE FROM projections.user_auth_methods4 WHERE (user_id = $1) AND (method_type = $2) AND (resource_owner = $3) AND (instance_id = $4)" ,
expectedArgs : [ ] interface { } {
"agg-id" ,
domain . UserAuthMethodTypeOTPEmail ,
"ro-id" ,
"instance-id" ,
} ,
} ,
} ,
} ,
} ,
} ,
2022-11-30 16:01:17 +00:00
{
name : "org reduceOwnerRemoved" ,
reduce : ( & userAuthMethodProjection { } ) . reduceOwnerRemoved ,
args : args {
event : getEvent ( testEvent (
repository . EventType ( org . OrgRemovedEventType ) ,
org . AggregateType ,
nil ,
) , org . OrgRemovedEventMapper ) ,
} ,
want : wantReduce {
aggregateType : eventstore . AggregateType ( "org" ) ,
sequence : 15 ,
previousSequence : 10 ,
executer : & testExecuter {
executions : [ ] execution {
{
expectedStmt : "UPDATE projections.user_auth_methods4 SET (change_date, sequence, owner_removed) = ($1, $2, $3) WHERE (instance_id = $4) AND (resource_owner = $5)" ,
expectedArgs : [ ] interface { } {
anyArg { } ,
uint64 ( 15 ) ,
true ,
"instance-id" ,
"agg-id" ,
} ,
} ,
} ,
} ,
} ,
} ,
2022-10-20 12:36:52 +00:00
{
2022-11-10 10:59:33 +00:00
name : "instance reduceInstanceRemoved" ,
2022-10-20 12:36:52 +00:00
args : args {
event : getEvent ( testEvent (
repository . EventType ( instance . InstanceRemovedEventType ) ,
instance . AggregateType ,
2022-10-26 13:06:48 +00:00
nil ,
2022-10-20 12:36:52 +00:00
) , instance . InstanceRemovedEventMapper ) ,
} ,
reduce : reduceInstanceRemovedHelper ( UserAuthMethodInstanceIDCol ) ,
want : wantReduce {
aggregateType : eventstore . AggregateType ( "instance" ) ,
sequence : 15 ,
previousSequence : 10 ,
executer : & testExecuter {
executions : [ ] execution {
{
2022-11-30 16:01:17 +00:00
expectedStmt : "DELETE FROM projections.user_auth_methods4 WHERE (instance_id = $1)" ,
2022-10-20 12:36:52 +00:00
expectedArgs : [ ] interface { } {
"agg-id" ,
} ,
} ,
} ,
} ,
} ,
} ,
2022-01-19 13:49:50 +00:00
}
for _ , tt := range tests {
t . Run ( tt . name , func ( t * testing . T ) {
event := baseEvent ( t )
got , err := tt . reduce ( event )
if _ , ok := err . ( errors . InvalidArgument ) ; ! ok {
t . Errorf ( "no wrong event mapping: %v, got: %v" , err , got )
}
event = tt . args . event ( t )
got , err = tt . reduce ( event )
2022-10-20 12:36:52 +00:00
assertReduce ( t , got , err , UserAuthMethodTable , tt . want )
2022-01-19 13:49:50 +00:00
} )
}
}