feat(session): TOTP Check API with relation tables (#11886)

# Which Problems Are Solved

As part of #11035 , this PR implements the TOTP check logic for session
validation

# How the Problems Are Solved

  - Implement TOTP check logic and tests
- The tarpit function has been moved to a common file so that it can be
used by both TOTP and password checks
- Manual transaction management to avoid stalling the DB while verifier
function is executed
- Update `database.Change` `Matches()` function to allow comparison of
`time.Time` values
  - A converter package from GRPC to Domain model has been added

# Additional Context

This is a cherry-picked PR + changes, coming from
https://github.com/zitadel/zitadel/pull/11164
- Relates to #11035
This commit is contained in:
Marco A.
2026-04-01 11:34:03 +02:00
committed by GitHub
parent 8c8fc47884
commit 701bca6003
9 changed files with 1283 additions and 17 deletions
@@ -0,0 +1,16 @@
package convert
import (
"github.com/zitadel/zitadel/backend/v3/domain"
session_grpc "github.com/zitadel/zitadel/pkg/grpc/session/v2"
)
func CheckTOTPGRPCToDomain(checkTOTP *session_grpc.CheckTOTP) *domain.CheckTOTPType {
if checkTOTP == nil {
return nil
}
return &domain.CheckTOTPType{
Code: checkTOTP.GetCode(),
}
}
@@ -0,0 +1,36 @@
package convert
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/zitadel/zitadel/backend/v3/domain"
session_grpc "github.com/zitadel/zitadel/pkg/grpc/session/v2"
)
func TestCheckTOTPGRPCToDomain(t *testing.T) {
t.Parallel()
tt := []struct {
name string
input *session_grpc.CheckTOTP
expected *domain.CheckTOTPType
}{
{name: "nil input returns nil"},
{
name: "code is mapped",
input: &session_grpc.CheckTOTP{Code: "123456"},
expected: &domain.CheckTOTPType{Code: "123456"},
},
}
for _, tc := range tt {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
got := CheckTOTPGRPCToDomain(tc.input)
assert.Equal(t, tc.expected, got)
})
}
}