2023-05-05 17:34:53 +02:00
package projection
import (
"testing"
"time"
2023-10-19 12:34:00 +02:00
"github.com/muhlemmer/gu"
2023-05-05 17:34:53 +02:00
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/eventstore"
2023-10-19 12:19:10 +02:00
"github.com/zitadel/zitadel/internal/eventstore/handler/v2"
2023-05-05 17:34:53 +02:00
"github.com/zitadel/zitadel/internal/repository/instance"
"github.com/zitadel/zitadel/internal/repository/session"
2023-06-20 17:34:06 +02:00
"github.com/zitadel/zitadel/internal/repository/user"
2023-05-05 17:34:53 +02:00
)
func TestSessionProjection_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 : "instance reduceSessionAdded" ,
args : args {
event : getEvent ( testEvent (
session . AddedType ,
session . AggregateType ,
2023-06-27 14:36:07 +02:00
[ ] byte ( ` {
2023-10-19 12:34:00 +02:00
"domain" : "domain" ,
"user_agent" : {
"fingerprint_id" : "fp1" ,
"ip" : "1.2.3.4" ,
"description" : "firefox" ,
"header" : {
"foo" : [ "bar" ]
}
}
2023-06-27 14:36:07 +02:00
} ` ) ,
2023-05-05 17:34:53 +02:00
) , session . AddedEventMapper ) ,
} ,
reduce : ( & sessionProjection { } ) . reduceSessionAdded ,
want : wantReduce {
2023-10-19 12:19:10 +02:00
aggregateType : eventstore . AggregateType ( "session" ) ,
sequence : 15 ,
2023-05-05 17:34:53 +02:00
executer : & testExecuter {
executions : [ ] execution {
{
2023-10-19 12:34:00 +02:00
expectedStmt : "INSERT INTO projections.sessions6 (id, instance_id, creation_date, change_date, resource_owner, state, sequence, creator, user_agent_fingerprint_id, user_agent_description, user_agent_ip, user_agent_header) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)" ,
2023-05-05 17:34:53 +02:00
expectedArgs : [ ] interface { } {
"agg-id" ,
"instance-id" ,
anyArg { } ,
anyArg { } ,
"ro-id" ,
domain . SessionStateActive ,
uint64 ( 15 ) ,
"editor-user" ,
2023-10-19 12:34:00 +02:00
gu . Ptr ( "fp1" ) ,
gu . Ptr ( "firefox" ) ,
"1.2.3.4" ,
[ ] byte ( ` { "foo":["bar"]} ` ) ,
2023-05-05 17:34:53 +02:00
} ,
} ,
} ,
} ,
} ,
} ,
{
name : "instance reduceUserChecked" ,
args : args {
event : getEvent ( testEvent (
session . AddedType ,
session . AggregateType ,
[ ] byte ( ` {
"userId" : "user-id" ,
"checkedAt" : "2023-05-04T00:00:00Z"
} ` ) ,
) , session . UserCheckedEventMapper ) ,
} ,
reduce : ( & sessionProjection { } ) . reduceUserChecked ,
want : wantReduce {
2023-10-19 12:19:10 +02:00
aggregateType : eventstore . AggregateType ( "session" ) ,
sequence : 15 ,
2023-05-05 17:34:53 +02:00
executer : & testExecuter {
executions : [ ] execution {
{
2023-10-19 12:34:00 +02:00
expectedStmt : "UPDATE projections.sessions6 SET (change_date, sequence, user_id, user_checked_at) = ($1, $2, $3, $4) WHERE (id = $5) AND (instance_id = $6)" ,
2023-05-05 17:34:53 +02:00
expectedArgs : [ ] interface { } {
anyArg { } ,
anyArg { } ,
"user-id" ,
time . Date ( 2023 , time . May , 4 , 0 , 0 , 0 , 0 , time . UTC ) ,
"agg-id" ,
"instance-id" ,
} ,
} ,
} ,
} ,
} ,
} ,
{
name : "instance reducePasswordChecked" ,
args : args {
event : getEvent ( testEvent (
session . AddedType ,
session . AggregateType ,
[ ] byte ( ` {
"checkedAt" : "2023-05-04T00:00:00Z"
} ` ) ,
) , session . PasswordCheckedEventMapper ) ,
} ,
reduce : ( & sessionProjection { } ) . reducePasswordChecked ,
want : wantReduce {
2023-10-19 12:19:10 +02:00
aggregateType : eventstore . AggregateType ( "session" ) ,
sequence : 15 ,
2023-05-05 17:34:53 +02:00
executer : & testExecuter {
executions : [ ] execution {
{
2023-10-19 12:34:00 +02:00
expectedStmt : "UPDATE projections.sessions6 SET (change_date, sequence, password_checked_at) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)" ,
2023-06-21 16:06:18 +02:00
expectedArgs : [ ] interface { } {
anyArg { } ,
anyArg { } ,
time . Date ( 2023 , time . May , 4 , 0 , 0 , 0 , 0 , time . UTC ) ,
"agg-id" ,
"instance-id" ,
} ,
} ,
} ,
} ,
} ,
} ,
2023-08-11 18:36:18 +03:00
{
name : "instance reduceWebAuthNChecked" ,
args : args {
event : getEvent ( testEvent (
session . WebAuthNCheckedType ,
session . AggregateType ,
[ ] byte ( ` {
"checkedAt" : "2023-05-04T00:00:00Z" ,
"userVerified" : true
} ` ) ,
) , eventstore . GenericEventMapper [ session . WebAuthNCheckedEvent ] ) ,
} ,
reduce : ( & sessionProjection { } ) . reduceWebAuthNChecked ,
want : wantReduce {
2023-10-19 12:19:10 +02:00
aggregateType : eventstore . AggregateType ( "session" ) ,
sequence : 15 ,
2023-08-11 18:36:18 +03:00
executer : & testExecuter {
executions : [ ] execution {
{
2023-10-19 12:34:00 +02:00
expectedStmt : "UPDATE projections.sessions6 SET (change_date, sequence, webauthn_checked_at, webauthn_user_verified) = ($1, $2, $3, $4) WHERE (id = $5) AND (instance_id = $6)" ,
2023-08-11 18:36:18 +03:00
expectedArgs : [ ] interface { } {
anyArg { } ,
anyArg { } ,
time . Date ( 2023 , time . May , 4 , 0 , 0 , 0 , 0 , time . UTC ) ,
true ,
"agg-id" ,
"instance-id" ,
} ,
} ,
} ,
} ,
} ,
} ,
2023-06-21 16:06:18 +02:00
{
name : "instance reduceIntentChecked" ,
args : args {
event : getEvent ( testEvent (
session . AddedType ,
session . AggregateType ,
[ ] byte ( ` {
"checkedAt" : "2023-05-04T00:00:00Z"
} ` ) ,
) , session . IntentCheckedEventMapper ) ,
} ,
reduce : ( & sessionProjection { } ) . reduceIntentChecked ,
want : wantReduce {
2023-10-19 12:19:10 +02:00
aggregateType : eventstore . AggregateType ( "session" ) ,
sequence : 15 ,
2023-06-21 16:06:18 +02:00
executer : & testExecuter {
executions : [ ] execution {
{
2023-10-19 12:34:00 +02:00
expectedStmt : "UPDATE projections.sessions6 SET (change_date, sequence, intent_checked_at) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)" ,
2023-05-05 17:34:53 +02:00
expectedArgs : [ ] interface { } {
anyArg { } ,
anyArg { } ,
time . Date ( 2023 , time . May , 4 , 0 , 0 , 0 , 0 , time . UTC ) ,
"agg-id" ,
"instance-id" ,
} ,
} ,
} ,
} ,
} ,
} ,
2023-08-15 12:50:42 +03:00
{
name : "instance reduceOTPChecked" ,
args : args {
event : getEvent ( testEvent (
session . AddedType ,
session . AggregateType ,
[ ] byte ( ` {
"checkedAt" : "2023-05-04T00:00:00Z"
} ` ) ,
) , eventstore . GenericEventMapper [ session . TOTPCheckedEvent ] ) ,
} ,
reduce : ( & sessionProjection { } ) . reduceTOTPChecked ,
want : wantReduce {
2023-10-19 12:19:10 +02:00
aggregateType : eventstore . AggregateType ( "session" ) ,
sequence : 15 ,
2023-08-15 12:50:42 +03:00
executer : & testExecuter {
executions : [ ] execution {
{
2023-10-19 12:34:00 +02:00
expectedStmt : "UPDATE projections.sessions6 SET (change_date, sequence, totp_checked_at) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)" ,
2023-08-15 12:50:42 +03:00
expectedArgs : [ ] interface { } {
anyArg { } ,
anyArg { } ,
time . Date ( 2023 , time . May , 4 , 0 , 0 , 0 , 0 , time . UTC ) ,
"agg-id" ,
"instance-id" ,
} ,
} ,
} ,
} ,
} ,
} ,
2023-05-05 17:34:53 +02:00
{
name : "instance reduceTokenSet" ,
args : args {
event : getEvent ( testEvent (
session . TokenSetType ,
session . AggregateType ,
[ ] byte ( ` {
"tokenID" : "tokenID"
} ` ) ,
) , session . TokenSetEventMapper ) ,
} ,
reduce : ( & sessionProjection { } ) . reduceTokenSet ,
want : wantReduce {
2023-10-19 12:19:10 +02:00
aggregateType : eventstore . AggregateType ( "session" ) ,
sequence : 15 ,
2023-05-05 17:34:53 +02:00
executer : & testExecuter {
executions : [ ] execution {
{
2023-10-19 12:34:00 +02:00
expectedStmt : "UPDATE projections.sessions6 SET (change_date, sequence, token_id) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)" ,
2023-05-05 17:34:53 +02:00
expectedArgs : [ ] interface { } {
anyArg { } ,
anyArg { } ,
"tokenID" ,
"agg-id" ,
"instance-id" ,
} ,
} ,
} ,
} ,
} ,
} ,
{
name : "instance reduceMetadataSet" ,
args : args {
event : getEvent ( testEvent (
session . MetadataSetType ,
session . AggregateType ,
[ ] byte ( ` {
"metadata" : {
"key" : "dmFsdWU="
}
} ` ) ,
) , session . MetadataSetEventMapper ) ,
} ,
reduce : ( & sessionProjection { } ) . reduceMetadataSet ,
want : wantReduce {
2023-10-19 12:19:10 +02:00
aggregateType : eventstore . AggregateType ( "session" ) ,
sequence : 15 ,
2023-05-05 17:34:53 +02:00
executer : & testExecuter {
executions : [ ] execution {
{
2023-10-19 12:34:00 +02:00
expectedStmt : "UPDATE projections.sessions6 SET (change_date, sequence, metadata) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)" ,
2023-05-05 17:34:53 +02:00
expectedArgs : [ ] interface { } {
anyArg { } ,
anyArg { } ,
map [ string ] [ ] byte {
"key" : [ ] byte ( "value" ) ,
} ,
"agg-id" ,
"instance-id" ,
} ,
} ,
} ,
} ,
} ,
} ,
{
name : "instance reduceSessionTerminated" ,
args : args {
event : getEvent ( testEvent (
session . TerminateType ,
session . AggregateType ,
[ ] byte ( ` { } ` ) ,
) , session . TerminateEventMapper ) ,
} ,
reduce : ( & sessionProjection { } ) . reduceSessionTerminated ,
want : wantReduce {
2023-10-19 12:19:10 +02:00
aggregateType : eventstore . AggregateType ( "session" ) ,
sequence : 15 ,
2023-05-05 17:34:53 +02:00
executer : & testExecuter {
executions : [ ] execution {
{
2023-10-19 12:34:00 +02:00
expectedStmt : "DELETE FROM projections.sessions6 WHERE (id = $1) AND (instance_id = $2)" ,
2023-05-05 17:34:53 +02:00
expectedArgs : [ ] interface { } {
"agg-id" ,
"instance-id" ,
} ,
} ,
} ,
} ,
} ,
} ,
{
name : "instance reduceInstanceRemoved" ,
args : args {
2023-10-19 12:19:10 +02:00
event : getEvent (
testEvent (
instance . InstanceRemovedEventType ,
instance . AggregateType ,
nil ,
) , instance . InstanceRemovedEventMapper ) ,
2023-05-05 17:34:53 +02:00
} ,
reduce : reduceInstanceRemovedHelper ( SessionColumnInstanceID ) ,
want : wantReduce {
2023-10-19 12:19:10 +02:00
aggregateType : eventstore . AggregateType ( "instance" ) ,
sequence : 15 ,
2023-05-05 17:34:53 +02:00
executer : & testExecuter {
executions : [ ] execution {
{
2023-10-19 12:34:00 +02:00
expectedStmt : "DELETE FROM projections.sessions6 WHERE (instance_id = $1)" ,
2023-05-05 17:34:53 +02:00
expectedArgs : [ ] interface { } {
"agg-id" ,
} ,
} ,
} ,
} ,
} ,
} ,
2023-06-20 17:34:06 +02:00
{
name : "reducePasswordChanged" ,
args : args {
event : getEvent ( testEvent (
2023-10-19 12:19:10 +02:00
user . HumanPasswordChangedType ,
2023-06-20 17:34:06 +02:00
user . AggregateType ,
[ ] byte ( ` { "secret" : {
"cryptoType" : 0 ,
"algorithm" : "enc" ,
"keyID" : "id" ,
"crypted" : "cGFzc3dvcmQ="
} } ` ) ,
) , user . HumanPasswordChangedEventMapper ) ,
} ,
reduce : ( & sessionProjection { } ) . reducePasswordChanged ,
want : wantReduce {
2023-10-19 12:19:10 +02:00
aggregateType : eventstore . AggregateType ( "user" ) ,
sequence : 15 ,
2023-06-20 17:34:06 +02:00
executer : & testExecuter {
executions : [ ] execution {
{
2023-10-19 12:34:00 +02:00
expectedStmt : "UPDATE projections.sessions6 SET password_checked_at = $1 WHERE (user_id = $2) AND (password_checked_at < $3)" ,
2023-06-20 17:34:06 +02:00
expectedArgs : [ ] interface { } {
nil ,
"agg-id" ,
anyArg { } ,
} ,
} ,
} ,
} ,
} ,
} ,
2023-05-05 17:34:53 +02:00
}
for _ , tt := range tests {
t . Run ( tt . name , func ( t * testing . T ) {
event := baseEvent ( t )
got , err := tt . reduce ( event )
if ! errors . IsErrorInvalidArgument ( err ) {
t . Errorf ( "no wrong event mapping: %v, got: %v" , err , got )
}
event = tt . args . event ( t )
got , err = tt . reduce ( event )
assertReduce ( t , got , err , SessionsProjectionTable , tt . want )
} )
}
}