mirror of
https://github.com/zitadel/zitadel.git
synced 2025-01-10 03:43:40 +00:00
fix: add integration tests for list sessions
This commit is contained in:
parent
3da2db0851
commit
7dd2e04866
@ -7,12 +7,15 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/golang/protobuf/ptypes/timestamp"
|
||||
"github.com/muhlemmer/gu"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/protobuf/types/known/durationpb"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/integration"
|
||||
"github.com/zitadel/zitadel/pkg/grpc/object/v2"
|
||||
"github.com/zitadel/zitadel/pkg/grpc/session/v2"
|
||||
)
|
||||
|
||||
@ -231,3 +234,358 @@ func TestServer_GetSession(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type sessionAttr struct {
|
||||
ID string
|
||||
UserID string
|
||||
UserAgent string
|
||||
CreationDate *timestamp.Timestamp
|
||||
ChangeDate *timestamppb.Timestamp
|
||||
Details *object.Details
|
||||
}
|
||||
|
||||
type sessionAttrs []*sessionAttr
|
||||
|
||||
func (u sessionAttrs) ids() []string {
|
||||
ids := make([]string, len(u))
|
||||
for i := range u {
|
||||
ids[i] = u[i].ID
|
||||
}
|
||||
return ids
|
||||
}
|
||||
|
||||
func createSessions(ctx context.Context, t *testing.T, count int, userID string, userAgent string, lifetime *durationpb.Duration, metadata map[string][]byte) sessionAttrs {
|
||||
infos := make([]*sessionAttr, count)
|
||||
for i := 0; i < count; i++ {
|
||||
infos[i] = createSession(ctx, t, userID, userAgent, lifetime, metadata)
|
||||
}
|
||||
return infos
|
||||
}
|
||||
|
||||
func createSession(ctx context.Context, t *testing.T, userID string, userAgent string, lifetime *durationpb.Duration, metadata map[string][]byte) *sessionAttr {
|
||||
req := &session.CreateSessionRequest{}
|
||||
if userID != "" {
|
||||
req.Checks = &session.Checks{
|
||||
User: &session.CheckUser{
|
||||
Search: &session.CheckUser_UserId{
|
||||
UserId: userID,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
if userAgent != "" {
|
||||
req.UserAgent = &session.UserAgent{
|
||||
FingerprintId: gu.Ptr(userAgent),
|
||||
Ip: gu.Ptr("1.2.3.4"),
|
||||
Description: gu.Ptr("Description"),
|
||||
Header: map[string]*session.UserAgent_HeaderValues{
|
||||
"foo": {Values: []string{"foo", "bar"}},
|
||||
},
|
||||
}
|
||||
}
|
||||
if lifetime != nil {
|
||||
req.Lifetime = lifetime
|
||||
}
|
||||
if metadata != nil {
|
||||
req.Metadata = metadata
|
||||
}
|
||||
resp, err := Client.CreateSession(ctx, req)
|
||||
require.NoError(t, err)
|
||||
return &sessionAttr{
|
||||
resp.GetSessionId(),
|
||||
userID,
|
||||
userAgent,
|
||||
resp.GetDetails().GetChangeDate(),
|
||||
resp.GetDetails().GetChangeDate(),
|
||||
resp.GetDetails(),
|
||||
}
|
||||
}
|
||||
|
||||
func TestServer_ListSessions(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
req *session.ListSessionsRequest
|
||||
dep func(ctx context.Context, t *testing.T, request *session.ListSessionsRequest) []*sessionAttr
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want *session.ListSessionsResponse
|
||||
wantFactors []wantFactor
|
||||
wantExpirationWindow time.Duration
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "list sessions, not found",
|
||||
args: args{
|
||||
CTX,
|
||||
&session.ListSessionsRequest{
|
||||
Queries: []*session.SearchQuery{
|
||||
{Query: &session.SearchQuery_IdsQuery{IdsQuery: &session.IDsQuery{Ids: []string{"unknown"}}}},
|
||||
},
|
||||
},
|
||||
func(ctx context.Context, t *testing.T, request *session.ListSessionsRequest) []*sessionAttr {
|
||||
return []*sessionAttr{}
|
||||
},
|
||||
},
|
||||
want: &session.ListSessionsResponse{
|
||||
Details: &object.ListDetails{
|
||||
TotalResult: 0,
|
||||
Timestamp: timestamppb.Now(),
|
||||
},
|
||||
Sessions: []*session.Session{},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "list sessions, no permission",
|
||||
args: args{
|
||||
UserCTX,
|
||||
&session.ListSessionsRequest{
|
||||
Queries: []*session.SearchQuery{},
|
||||
},
|
||||
func(ctx context.Context, t *testing.T, request *session.ListSessionsRequest) []*sessionAttr {
|
||||
info := createSession(ctx, t, "", "", nil, nil)
|
||||
request.Queries = append(request.Queries, &session.SearchQuery{Query: &session.SearchQuery_IdsQuery{IdsQuery: &session.IDsQuery{Ids: []string{info.ID}}}})
|
||||
return []*sessionAttr{}
|
||||
},
|
||||
},
|
||||
want: &session.ListSessionsResponse{
|
||||
Details: &object.ListDetails{
|
||||
TotalResult: 1,
|
||||
Timestamp: timestamppb.Now(),
|
||||
},
|
||||
Sessions: []*session.Session{},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "list sessions, permission, ok",
|
||||
args: args{
|
||||
CTX,
|
||||
&session.ListSessionsRequest{},
|
||||
func(ctx context.Context, t *testing.T, request *session.ListSessionsRequest) []*sessionAttr {
|
||||
info := createSession(ctx, t, "", "", nil, nil)
|
||||
request.Queries = append(request.Queries, &session.SearchQuery{Query: &session.SearchQuery_IdsQuery{IdsQuery: &session.IDsQuery{Ids: []string{info.ID}}}})
|
||||
return []*sessionAttr{info}
|
||||
},
|
||||
},
|
||||
want: &session.ListSessionsResponse{
|
||||
Details: &object.ListDetails{
|
||||
TotalResult: 1,
|
||||
Timestamp: timestamppb.Now(),
|
||||
},
|
||||
Sessions: []*session.Session{{}},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "list sessions, full, ok",
|
||||
args: args{
|
||||
CTX,
|
||||
&session.ListSessionsRequest{},
|
||||
func(ctx context.Context, t *testing.T, request *session.ListSessionsRequest) []*sessionAttr {
|
||||
info := createSession(ctx, t, User.GetUserId(), "agent", durationpb.New(time.Minute*5), map[string][]byte{"key": []byte("value")})
|
||||
request.Queries = append(request.Queries, &session.SearchQuery{Query: &session.SearchQuery_IdsQuery{IdsQuery: &session.IDsQuery{Ids: []string{info.ID}}}})
|
||||
return []*sessionAttr{info}
|
||||
},
|
||||
},
|
||||
wantExpirationWindow: time.Minute * 5,
|
||||
wantFactors: []wantFactor{wantUserFactor},
|
||||
want: &session.ListSessionsResponse{
|
||||
Details: &object.ListDetails{
|
||||
TotalResult: 1,
|
||||
Timestamp: timestamppb.Now(),
|
||||
},
|
||||
Sessions: []*session.Session{
|
||||
{
|
||||
Metadata: map[string][]byte{"key": []byte("value")},
|
||||
UserAgent: &session.UserAgent{
|
||||
FingerprintId: gu.Ptr("agent"),
|
||||
Ip: gu.Ptr("1.2.3.4"),
|
||||
Description: gu.Ptr("Description"),
|
||||
Header: map[string]*session.UserAgent_HeaderValues{
|
||||
"foo": {Values: []string{"foo", "bar"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "list sessions, multiple, ok",
|
||||
args: args{
|
||||
CTX,
|
||||
&session.ListSessionsRequest{},
|
||||
func(ctx context.Context, t *testing.T, request *session.ListSessionsRequest) []*sessionAttr {
|
||||
infos := createSessions(ctx, t, 3, User.GetUserId(), "agent", durationpb.New(time.Minute*5), map[string][]byte{"key": []byte("value")})
|
||||
request.Queries = append(request.Queries, &session.SearchQuery{Query: &session.SearchQuery_IdsQuery{IdsQuery: &session.IDsQuery{Ids: infos.ids()}}})
|
||||
return infos
|
||||
},
|
||||
},
|
||||
wantExpirationWindow: time.Minute * 5,
|
||||
wantFactors: []wantFactor{wantUserFactor},
|
||||
want: &session.ListSessionsResponse{
|
||||
Details: &object.ListDetails{
|
||||
TotalResult: 3,
|
||||
Timestamp: timestamppb.Now(),
|
||||
},
|
||||
Sessions: []*session.Session{
|
||||
{
|
||||
Metadata: map[string][]byte{"key": []byte("value")},
|
||||
UserAgent: &session.UserAgent{
|
||||
FingerprintId: gu.Ptr("agent"),
|
||||
Ip: gu.Ptr("1.2.3.4"),
|
||||
Description: gu.Ptr("Description"),
|
||||
Header: map[string]*session.UserAgent_HeaderValues{
|
||||
"foo": {Values: []string{"foo", "bar"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Metadata: map[string][]byte{"key": []byte("value")},
|
||||
UserAgent: &session.UserAgent{
|
||||
FingerprintId: gu.Ptr("agent"),
|
||||
Ip: gu.Ptr("1.2.3.4"),
|
||||
Description: gu.Ptr("Description"),
|
||||
Header: map[string]*session.UserAgent_HeaderValues{
|
||||
"foo": {Values: []string{"foo", "bar"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Metadata: map[string][]byte{"key": []byte("value")},
|
||||
UserAgent: &session.UserAgent{
|
||||
FingerprintId: gu.Ptr("agent"),
|
||||
Ip: gu.Ptr("1.2.3.4"),
|
||||
Description: gu.Ptr("Description"),
|
||||
Header: map[string]*session.UserAgent_HeaderValues{
|
||||
"foo": {Values: []string{"foo", "bar"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "list sessions, userid, ok",
|
||||
args: args{
|
||||
CTX,
|
||||
&session.ListSessionsRequest{},
|
||||
func(ctx context.Context, t *testing.T, request *session.ListSessionsRequest) []*sessionAttr {
|
||||
createdUser := createFullUser(ctx)
|
||||
info := createSession(ctx, t, createdUser.GetUserId(), "agent", durationpb.New(time.Minute*5), map[string][]byte{"key": []byte("value")})
|
||||
request.Queries = append(request.Queries, &session.SearchQuery{Query: &session.SearchQuery_UserIdQuery{UserIdQuery: &session.UserIDQuery{Id: createdUser.GetUserId()}}})
|
||||
return []*sessionAttr{info}
|
||||
},
|
||||
},
|
||||
wantExpirationWindow: time.Minute * 5,
|
||||
wantFactors: []wantFactor{wantUserFactor},
|
||||
want: &session.ListSessionsResponse{
|
||||
Details: &object.ListDetails{
|
||||
TotalResult: 1,
|
||||
Timestamp: timestamppb.Now(),
|
||||
},
|
||||
Sessions: []*session.Session{
|
||||
{
|
||||
Metadata: map[string][]byte{"key": []byte("value")},
|
||||
UserAgent: &session.UserAgent{
|
||||
FingerprintId: gu.Ptr("agent"),
|
||||
Ip: gu.Ptr("1.2.3.4"),
|
||||
Description: gu.Ptr("Description"),
|
||||
Header: map[string]*session.UserAgent_HeaderValues{
|
||||
"foo": {Values: []string{"foo", "bar"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "list sessions, creator, ok",
|
||||
args: args{
|
||||
CTX,
|
||||
&session.ListSessionsRequest{},
|
||||
func(ctx context.Context, t *testing.T, request *session.ListSessionsRequest) []*sessionAttr {
|
||||
info := createSession(ctx, t, User.GetUserId(), "agent", durationpb.New(time.Minute*5), map[string][]byte{"key": []byte("value")})
|
||||
request.Queries = append(request.Queries,
|
||||
&session.SearchQuery{Query: &session.SearchQuery_IdsQuery{IdsQuery: &session.IDsQuery{Ids: []string{info.ID}}}},
|
||||
&session.SearchQuery{Query: &session.SearchQuery_OwnCreatorQuery{OwnCreatorQuery: &session.OwnCreatorQuery{}}})
|
||||
return []*sessionAttr{info}
|
||||
},
|
||||
},
|
||||
wantExpirationWindow: time.Minute * 5,
|
||||
wantFactors: []wantFactor{wantUserFactor},
|
||||
want: &session.ListSessionsResponse{
|
||||
Details: &object.ListDetails{
|
||||
TotalResult: 1,
|
||||
Timestamp: timestamppb.Now(),
|
||||
},
|
||||
Sessions: []*session.Session{
|
||||
{
|
||||
Metadata: map[string][]byte{"key": []byte("value")},
|
||||
UserAgent: &session.UserAgent{
|
||||
FingerprintId: gu.Ptr("agent"),
|
||||
Ip: gu.Ptr("1.2.3.4"),
|
||||
Description: gu.Ptr("Description"),
|
||||
Header: map[string]*session.UserAgent_HeaderValues{
|
||||
"foo": {Values: []string{"foo", "bar"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "list sessions, wrong creator",
|
||||
args: args{
|
||||
IAMOwnerCTX,
|
||||
&session.ListSessionsRequest{},
|
||||
func(ctx context.Context, t *testing.T, request *session.ListSessionsRequest) []*sessionAttr {
|
||||
info := createSession(ctx, t, User.GetUserId(), "agent", durationpb.New(time.Minute*5), map[string][]byte{"key": []byte("value")})
|
||||
request.Queries = append(request.Queries,
|
||||
&session.SearchQuery{Query: &session.SearchQuery_IdsQuery{IdsQuery: &session.IDsQuery{Ids: []string{info.ID}}}},
|
||||
&session.SearchQuery{Query: &session.SearchQuery_OwnCreatorQuery{OwnCreatorQuery: &session.OwnCreatorQuery{}}})
|
||||
return []*sessionAttr{}
|
||||
},
|
||||
},
|
||||
wantExpirationWindow: time.Minute * 5,
|
||||
wantFactors: []wantFactor{wantUserFactor},
|
||||
want: &session.ListSessionsResponse{
|
||||
Details: &object.ListDetails{
|
||||
TotalResult: 0,
|
||||
Timestamp: timestamppb.Now(),
|
||||
},
|
||||
Sessions: []*session.Session{},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
infos := tt.args.dep(CTX, t, tt.args.req)
|
||||
|
||||
retryDuration, tick := integration.WaitForAndTickWithMaxDuration(tt.args.ctx, time.Minute)
|
||||
require.EventuallyWithT(t, func(ttt *assert.CollectT) {
|
||||
got, err := Client.ListSessions(tt.args.ctx, tt.args.req)
|
||||
if tt.wantErr {
|
||||
assert.Error(ttt, err)
|
||||
return
|
||||
}
|
||||
if !assert.NoError(ttt, err) {
|
||||
return
|
||||
}
|
||||
|
||||
if !assert.Equal(ttt, got.Details.TotalResult, tt.want.Details.TotalResult) || !assert.Len(ttt, got.Sessions, len(tt.want.Sessions)) {
|
||||
return
|
||||
}
|
||||
|
||||
for i := range infos {
|
||||
tt.want.Sessions[i].Id = infos[i].ID
|
||||
tt.want.Sessions[i].Sequence = infos[i].Details.GetSequence()
|
||||
tt.want.Sessions[i].CreationDate = infos[i].Details.GetChangeDate()
|
||||
tt.want.Sessions[i].ChangeDate = infos[i].Details.GetChangeDate()
|
||||
|
||||
verifySession(ttt, got.Sessions[i], tt.want.Sessions[i], time.Minute, tt.wantExpirationWindow, infos[i].UserID, tt.wantFactors...)
|
||||
}
|
||||
integration.AssertListDetails(ttt, tt.want, got)
|
||||
}, retryDuration, tick)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
512
internal/api/grpc/session/v2beta/integration_test/query_test.go
Normal file
512
internal/api/grpc/session/v2beta/integration_test/query_test.go
Normal file
@ -0,0 +1,512 @@
|
||||
//go:build integration
|
||||
|
||||
package session_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/golang/protobuf/ptypes/timestamp"
|
||||
"github.com/muhlemmer/gu"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/protobuf/types/known/durationpb"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/integration"
|
||||
object "github.com/zitadel/zitadel/pkg/grpc/object/v2beta"
|
||||
session "github.com/zitadel/zitadel/pkg/grpc/session/v2beta"
|
||||
)
|
||||
|
||||
func TestServer_GetSession(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
req *session.GetSessionRequest
|
||||
dep func(ctx context.Context, t *testing.T, request *session.GetSessionRequest) uint64
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want *session.GetSessionResponse
|
||||
wantFactors []wantFactor
|
||||
wantExpirationWindow time.Duration
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "get session, no id provided",
|
||||
args: args{
|
||||
CTX,
|
||||
&session.GetSessionRequest{
|
||||
SessionId: "",
|
||||
},
|
||||
nil,
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "get session, not found",
|
||||
args: args{
|
||||
CTX,
|
||||
&session.GetSessionRequest{
|
||||
SessionId: "unknown",
|
||||
},
|
||||
nil,
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "get session, no permission",
|
||||
args: args{
|
||||
UserCTX,
|
||||
&session.GetSessionRequest{},
|
||||
func(ctx context.Context, t *testing.T, request *session.GetSessionRequest) uint64 {
|
||||
resp, err := Client.CreateSession(CTX, &session.CreateSessionRequest{})
|
||||
require.NoError(t, err)
|
||||
request.SessionId = resp.SessionId
|
||||
return resp.GetDetails().GetSequence()
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "get session, permission, ok",
|
||||
args: args{
|
||||
CTX,
|
||||
&session.GetSessionRequest{},
|
||||
func(ctx context.Context, t *testing.T, request *session.GetSessionRequest) uint64 {
|
||||
resp, err := Client.CreateSession(CTX, &session.CreateSessionRequest{})
|
||||
require.NoError(t, err)
|
||||
request.SessionId = resp.SessionId
|
||||
return resp.GetDetails().GetSequence()
|
||||
},
|
||||
},
|
||||
want: &session.GetSessionResponse{
|
||||
Session: &session.Session{},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "get session, token, ok",
|
||||
args: args{
|
||||
UserCTX,
|
||||
&session.GetSessionRequest{},
|
||||
func(ctx context.Context, t *testing.T, request *session.GetSessionRequest) uint64 {
|
||||
resp, err := Client.CreateSession(CTX, &session.CreateSessionRequest{})
|
||||
require.NoError(t, err)
|
||||
request.SessionId = resp.SessionId
|
||||
request.SessionToken = gu.Ptr(resp.SessionToken)
|
||||
return resp.GetDetails().GetSequence()
|
||||
},
|
||||
},
|
||||
want: &session.GetSessionResponse{
|
||||
Session: &session.Session{},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "get session, user agent, ok",
|
||||
args: args{
|
||||
UserCTX,
|
||||
&session.GetSessionRequest{},
|
||||
func(ctx context.Context, t *testing.T, request *session.GetSessionRequest) uint64 {
|
||||
resp, err := Client.CreateSession(CTX, &session.CreateSessionRequest{
|
||||
UserAgent: &session.UserAgent{
|
||||
FingerprintId: gu.Ptr("fingerPrintID"),
|
||||
Ip: gu.Ptr("1.2.3.4"),
|
||||
Description: gu.Ptr("Description"),
|
||||
Header: map[string]*session.UserAgent_HeaderValues{
|
||||
"foo": {Values: []string{"foo", "bar"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
request.SessionId = resp.SessionId
|
||||
request.SessionToken = gu.Ptr(resp.SessionToken)
|
||||
return resp.GetDetails().GetSequence()
|
||||
},
|
||||
},
|
||||
want: &session.GetSessionResponse{
|
||||
Session: &session.Session{
|
||||
UserAgent: &session.UserAgent{
|
||||
FingerprintId: gu.Ptr("fingerPrintID"),
|
||||
Ip: gu.Ptr("1.2.3.4"),
|
||||
Description: gu.Ptr("Description"),
|
||||
Header: map[string]*session.UserAgent_HeaderValues{
|
||||
"foo": {Values: []string{"foo", "bar"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "get session, lifetime, ok",
|
||||
args: args{
|
||||
UserCTX,
|
||||
&session.GetSessionRequest{},
|
||||
func(ctx context.Context, t *testing.T, request *session.GetSessionRequest) uint64 {
|
||||
resp, err := Client.CreateSession(CTX, &session.CreateSessionRequest{
|
||||
Lifetime: durationpb.New(5 * time.Minute),
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
request.SessionId = resp.SessionId
|
||||
request.SessionToken = gu.Ptr(resp.SessionToken)
|
||||
return resp.GetDetails().GetSequence()
|
||||
},
|
||||
},
|
||||
wantExpirationWindow: 5 * time.Minute,
|
||||
want: &session.GetSessionResponse{
|
||||
Session: &session.Session{},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "get session, metadata, ok",
|
||||
args: args{
|
||||
UserCTX,
|
||||
&session.GetSessionRequest{},
|
||||
func(ctx context.Context, t *testing.T, request *session.GetSessionRequest) uint64 {
|
||||
resp, err := Client.CreateSession(CTX, &session.CreateSessionRequest{
|
||||
Metadata: map[string][]byte{"foo": []byte("bar")},
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
request.SessionId = resp.SessionId
|
||||
request.SessionToken = gu.Ptr(resp.SessionToken)
|
||||
return resp.GetDetails().GetSequence()
|
||||
},
|
||||
},
|
||||
want: &session.GetSessionResponse{
|
||||
Session: &session.Session{
|
||||
Metadata: map[string][]byte{"foo": []byte("bar")},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "get session, user, ok",
|
||||
args: args{
|
||||
UserCTX,
|
||||
&session.GetSessionRequest{},
|
||||
func(ctx context.Context, t *testing.T, request *session.GetSessionRequest) uint64 {
|
||||
resp, err := Client.CreateSession(CTX, &session.CreateSessionRequest{
|
||||
Checks: &session.Checks{
|
||||
User: &session.CheckUser{
|
||||
Search: &session.CheckUser_UserId{
|
||||
UserId: User.GetUserId(),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
request.SessionId = resp.SessionId
|
||||
request.SessionToken = gu.Ptr(resp.SessionToken)
|
||||
return resp.GetDetails().GetSequence()
|
||||
},
|
||||
},
|
||||
wantFactors: []wantFactor{wantUserFactor},
|
||||
want: &session.GetSessionResponse{
|
||||
Session: &session.Session{},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
var sequence uint64
|
||||
if tt.args.dep != nil {
|
||||
sequence = tt.args.dep(tt.args.ctx, t, tt.args.req)
|
||||
}
|
||||
|
||||
retryDuration, tick := integration.WaitForAndTickWithMaxDuration(tt.args.ctx, time.Minute)
|
||||
require.EventuallyWithT(t, func(ttt *assert.CollectT) {
|
||||
got, err := Client.GetSession(tt.args.ctx, tt.args.req)
|
||||
if tt.wantErr {
|
||||
assert.Error(ttt, err)
|
||||
return
|
||||
}
|
||||
if !assert.NoError(ttt, err) {
|
||||
return
|
||||
}
|
||||
|
||||
tt.want.Session.Id = tt.args.req.SessionId
|
||||
tt.want.Session.Sequence = sequence
|
||||
verifySession(ttt, got.GetSession(), tt.want.GetSession(), time.Minute, tt.wantExpirationWindow, User.GetUserId(), tt.wantFactors...)
|
||||
}, retryDuration, tick)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type sessionAttr struct {
|
||||
ID string
|
||||
UserID string
|
||||
UserAgent string
|
||||
CreationDate *timestamp.Timestamp
|
||||
ChangeDate *timestamppb.Timestamp
|
||||
Details *object.Details
|
||||
}
|
||||
|
||||
type sessionAttrs []*sessionAttr
|
||||
|
||||
func (u sessionAttrs) ids() []string {
|
||||
ids := make([]string, len(u))
|
||||
for i := range u {
|
||||
ids[i] = u[i].ID
|
||||
}
|
||||
return ids
|
||||
}
|
||||
|
||||
func createSessions(ctx context.Context, t *testing.T, count int, userID string, userAgent string, lifetime *durationpb.Duration, metadata map[string][]byte) sessionAttrs {
|
||||
infos := make([]*sessionAttr, count)
|
||||
for i := 0; i < count; i++ {
|
||||
infos[i] = createSession(ctx, t, userID, userAgent, lifetime, metadata)
|
||||
}
|
||||
return infos
|
||||
}
|
||||
|
||||
func createSession(ctx context.Context, t *testing.T, userID string, userAgent string, lifetime *durationpb.Duration, metadata map[string][]byte) *sessionAttr {
|
||||
req := &session.CreateSessionRequest{}
|
||||
if userID != "" {
|
||||
req.Checks = &session.Checks{
|
||||
User: &session.CheckUser{
|
||||
Search: &session.CheckUser_UserId{
|
||||
UserId: userID,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
if userAgent != "" {
|
||||
req.UserAgent = &session.UserAgent{
|
||||
FingerprintId: gu.Ptr(userAgent),
|
||||
Ip: gu.Ptr("1.2.3.4"),
|
||||
Description: gu.Ptr("Description"),
|
||||
Header: map[string]*session.UserAgent_HeaderValues{
|
||||
"foo": {Values: []string{"foo", "bar"}},
|
||||
},
|
||||
}
|
||||
}
|
||||
if lifetime != nil {
|
||||
req.Lifetime = lifetime
|
||||
}
|
||||
if metadata != nil {
|
||||
req.Metadata = metadata
|
||||
}
|
||||
resp, err := Client.CreateSession(ctx, req)
|
||||
require.NoError(t, err)
|
||||
return &sessionAttr{
|
||||
resp.GetSessionId(),
|
||||
userID,
|
||||
userAgent,
|
||||
resp.GetDetails().GetChangeDate(),
|
||||
resp.GetDetails().GetChangeDate(),
|
||||
resp.GetDetails(),
|
||||
}
|
||||
}
|
||||
|
||||
func TestServer_ListSessions(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
req *session.ListSessionsRequest
|
||||
dep func(ctx context.Context, t *testing.T, request *session.ListSessionsRequest) []*sessionAttr
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want *session.ListSessionsResponse
|
||||
wantFactors []wantFactor
|
||||
wantExpirationWindow time.Duration
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "list sessions, not found",
|
||||
args: args{
|
||||
CTX,
|
||||
&session.ListSessionsRequest{
|
||||
Queries: []*session.SearchQuery{
|
||||
{Query: &session.SearchQuery_IdsQuery{IdsQuery: &session.IDsQuery{Ids: []string{"unknown"}}}},
|
||||
},
|
||||
},
|
||||
func(ctx context.Context, t *testing.T, request *session.ListSessionsRequest) []*sessionAttr {
|
||||
return []*sessionAttr{}
|
||||
},
|
||||
},
|
||||
want: &session.ListSessionsResponse{
|
||||
Details: &object.ListDetails{
|
||||
TotalResult: 0,
|
||||
Timestamp: timestamppb.Now(),
|
||||
},
|
||||
Sessions: []*session.Session{},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "list sessions, wrong creator",
|
||||
args: args{
|
||||
UserCTX,
|
||||
&session.ListSessionsRequest{},
|
||||
func(ctx context.Context, t *testing.T, request *session.ListSessionsRequest) []*sessionAttr {
|
||||
info := createSession(ctx, t, "", "", nil, nil)
|
||||
request.Queries = append(request.Queries, &session.SearchQuery{Query: &session.SearchQuery_IdsQuery{IdsQuery: &session.IDsQuery{Ids: []string{info.ID}}}})
|
||||
return []*sessionAttr{}
|
||||
},
|
||||
},
|
||||
want: &session.ListSessionsResponse{
|
||||
Details: &object.ListDetails{
|
||||
TotalResult: 0,
|
||||
Timestamp: timestamppb.Now(),
|
||||
},
|
||||
Sessions: []*session.Session{},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "list sessions, full, ok",
|
||||
args: args{
|
||||
CTX,
|
||||
&session.ListSessionsRequest{},
|
||||
func(ctx context.Context, t *testing.T, request *session.ListSessionsRequest) []*sessionAttr {
|
||||
info := createSession(ctx, t, User.GetUserId(), "agent", durationpb.New(time.Minute*5), map[string][]byte{"key": []byte("value")})
|
||||
request.Queries = append(request.Queries, &session.SearchQuery{Query: &session.SearchQuery_IdsQuery{IdsQuery: &session.IDsQuery{Ids: []string{info.ID}}}})
|
||||
return []*sessionAttr{info}
|
||||
},
|
||||
},
|
||||
wantExpirationWindow: time.Minute * 5,
|
||||
wantFactors: []wantFactor{wantUserFactor},
|
||||
want: &session.ListSessionsResponse{
|
||||
Details: &object.ListDetails{
|
||||
TotalResult: 1,
|
||||
Timestamp: timestamppb.Now(),
|
||||
},
|
||||
Sessions: []*session.Session{
|
||||
{
|
||||
Metadata: map[string][]byte{"key": []byte("value")},
|
||||
UserAgent: &session.UserAgent{
|
||||
FingerprintId: gu.Ptr("agent"),
|
||||
Ip: gu.Ptr("1.2.3.4"),
|
||||
Description: gu.Ptr("Description"),
|
||||
Header: map[string]*session.UserAgent_HeaderValues{
|
||||
"foo": {Values: []string{"foo", "bar"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "list sessions, multiple, ok",
|
||||
args: args{
|
||||
CTX,
|
||||
&session.ListSessionsRequest{},
|
||||
func(ctx context.Context, t *testing.T, request *session.ListSessionsRequest) []*sessionAttr {
|
||||
infos := createSessions(ctx, t, 3, User.GetUserId(), "agent", durationpb.New(time.Minute*5), map[string][]byte{"key": []byte("value")})
|
||||
request.Queries = append(request.Queries, &session.SearchQuery{Query: &session.SearchQuery_IdsQuery{IdsQuery: &session.IDsQuery{Ids: infos.ids()}}})
|
||||
return infos
|
||||
},
|
||||
},
|
||||
wantExpirationWindow: time.Minute * 5,
|
||||
wantFactors: []wantFactor{wantUserFactor},
|
||||
want: &session.ListSessionsResponse{
|
||||
Details: &object.ListDetails{
|
||||
TotalResult: 3,
|
||||
Timestamp: timestamppb.Now(),
|
||||
},
|
||||
Sessions: []*session.Session{
|
||||
{
|
||||
Metadata: map[string][]byte{"key": []byte("value")},
|
||||
UserAgent: &session.UserAgent{
|
||||
FingerprintId: gu.Ptr("agent"),
|
||||
Ip: gu.Ptr("1.2.3.4"),
|
||||
Description: gu.Ptr("Description"),
|
||||
Header: map[string]*session.UserAgent_HeaderValues{
|
||||
"foo": {Values: []string{"foo", "bar"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Metadata: map[string][]byte{"key": []byte("value")},
|
||||
UserAgent: &session.UserAgent{
|
||||
FingerprintId: gu.Ptr("agent"),
|
||||
Ip: gu.Ptr("1.2.3.4"),
|
||||
Description: gu.Ptr("Description"),
|
||||
Header: map[string]*session.UserAgent_HeaderValues{
|
||||
"foo": {Values: []string{"foo", "bar"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Metadata: map[string][]byte{"key": []byte("value")},
|
||||
UserAgent: &session.UserAgent{
|
||||
FingerprintId: gu.Ptr("agent"),
|
||||
Ip: gu.Ptr("1.2.3.4"),
|
||||
Description: gu.Ptr("Description"),
|
||||
Header: map[string]*session.UserAgent_HeaderValues{
|
||||
"foo": {Values: []string{"foo", "bar"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "list sessions, userid, ok",
|
||||
args: args{
|
||||
CTX,
|
||||
&session.ListSessionsRequest{},
|
||||
func(ctx context.Context, t *testing.T, request *session.ListSessionsRequest) []*sessionAttr {
|
||||
createdUser := createFullUser(ctx)
|
||||
info := createSession(ctx, t, createdUser.GetUserId(), "agent", durationpb.New(time.Minute*5), map[string][]byte{"key": []byte("value")})
|
||||
request.Queries = append(request.Queries, &session.SearchQuery{Query: &session.SearchQuery_UserIdQuery{UserIdQuery: &session.UserIDQuery{Id: createdUser.GetUserId()}}})
|
||||
return []*sessionAttr{info}
|
||||
},
|
||||
},
|
||||
wantExpirationWindow: time.Minute * 5,
|
||||
wantFactors: []wantFactor{wantUserFactor},
|
||||
want: &session.ListSessionsResponse{
|
||||
Details: &object.ListDetails{
|
||||
TotalResult: 1,
|
||||
Timestamp: timestamppb.Now(),
|
||||
},
|
||||
Sessions: []*session.Session{
|
||||
{
|
||||
Metadata: map[string][]byte{"key": []byte("value")},
|
||||
UserAgent: &session.UserAgent{
|
||||
FingerprintId: gu.Ptr("agent"),
|
||||
Ip: gu.Ptr("1.2.3.4"),
|
||||
Description: gu.Ptr("Description"),
|
||||
Header: map[string]*session.UserAgent_HeaderValues{
|
||||
"foo": {Values: []string{"foo", "bar"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
infos := tt.args.dep(CTX, t, tt.args.req)
|
||||
|
||||
retryDuration, tick := integration.WaitForAndTickWithMaxDuration(tt.args.ctx, time.Minute)
|
||||
require.EventuallyWithT(t, func(ttt *assert.CollectT) {
|
||||
got, err := Client.ListSessions(tt.args.ctx, tt.args.req)
|
||||
if tt.wantErr {
|
||||
assert.Error(ttt, err)
|
||||
return
|
||||
}
|
||||
if !assert.NoError(ttt, err) {
|
||||
return
|
||||
}
|
||||
|
||||
if !assert.Equal(ttt, got.Details.TotalResult, tt.want.Details.TotalResult) || !assert.Len(ttt, got.Sessions, len(tt.want.Sessions)) {
|
||||
return
|
||||
}
|
||||
|
||||
for i := range infos {
|
||||
tt.want.Sessions[i].Id = infos[i].ID
|
||||
tt.want.Sessions[i].Sequence = infos[i].Details.GetSequence()
|
||||
tt.want.Sessions[i].CreationDate = infos[i].Details.GetChangeDate()
|
||||
tt.want.Sessions[i].ChangeDate = infos[i].Details.GetChangeDate()
|
||||
|
||||
verifySession(ttt, got.Sessions[i], tt.want.Sessions[i], time.Minute, tt.wantExpirationWindow, infos[i].UserID, tt.wantFactors...)
|
||||
}
|
||||
integration.AssertListDetails(ttt, tt.want, got)
|
||||
}, retryDuration, tick)
|
||||
})
|
||||
}
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
//go:build integration
|
||||
|
||||
package session_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/logging"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/integration"
|
||||
session "github.com/zitadel/zitadel/pkg/grpc/session/v2beta"
|
||||
"github.com/zitadel/zitadel/pkg/grpc/user/v2"
|
||||
)
|
||||
|
||||
var (
|
||||
CTX context.Context
|
||||
IAMOwnerCTX context.Context
|
||||
UserCTX context.Context
|
||||
Instance *integration.Instance
|
||||
Client session.SessionServiceClient
|
||||
User *user.AddHumanUserResponse
|
||||
DeactivatedUser *user.AddHumanUserResponse
|
||||
LockedUser *user.AddHumanUserResponse
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
os.Exit(func() int {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Minute)
|
||||
defer cancel()
|
||||
|
||||
Instance = integration.NewInstance(ctx)
|
||||
Client = Instance.Client.SessionV2beta
|
||||
|
||||
CTX = Instance.WithAuthorization(ctx, integration.UserTypeOrgOwner)
|
||||
IAMOwnerCTX = Instance.WithAuthorization(ctx, integration.UserTypeIAMOwner)
|
||||
UserCTX = Instance.WithAuthorization(ctx, integration.UserTypeNoPermission)
|
||||
User = createFullUser(CTX)
|
||||
DeactivatedUser = createDeactivatedUser(CTX)
|
||||
LockedUser = createLockedUser(CTX)
|
||||
return m.Run()
|
||||
}())
|
||||
}
|
||||
|
||||
func createFullUser(ctx context.Context) *user.AddHumanUserResponse {
|
||||
userResp := Instance.CreateHumanUser(ctx)
|
||||
Instance.Client.UserV2.VerifyEmail(ctx, &user.VerifyEmailRequest{
|
||||
UserId: userResp.GetUserId(),
|
||||
VerificationCode: userResp.GetEmailCode(),
|
||||
})
|
||||
Instance.Client.UserV2.VerifyPhone(ctx, &user.VerifyPhoneRequest{
|
||||
UserId: userResp.GetUserId(),
|
||||
VerificationCode: userResp.GetPhoneCode(),
|
||||
})
|
||||
Instance.SetUserPassword(ctx, userResp.GetUserId(), integration.UserPassword, false)
|
||||
Instance.RegisterUserPasskey(ctx, userResp.GetUserId())
|
||||
return userResp
|
||||
}
|
||||
|
||||
func createDeactivatedUser(ctx context.Context) *user.AddHumanUserResponse {
|
||||
userResp := Instance.CreateHumanUser(ctx)
|
||||
_, err := Instance.Client.UserV2.DeactivateUser(ctx, &user.DeactivateUserRequest{UserId: userResp.GetUserId()})
|
||||
logging.OnError(err).Fatal("deactivate human user")
|
||||
return userResp
|
||||
}
|
||||
|
||||
func createLockedUser(ctx context.Context) *user.AddHumanUserResponse {
|
||||
userResp := Instance.CreateHumanUser(ctx)
|
||||
_, err := Instance.Client.UserV2.LockUser(ctx, &user.LockUserRequest{UserId: userResp.GetUserId()})
|
||||
logging.OnError(err).Fatal("lock human user")
|
||||
return userResp
|
||||
}
|
@ -5,7 +5,6 @@ package session_test
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@ -14,7 +13,6 @@ import (
|
||||
"github.com/pquerna/otp/totp"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/zitadel/logging"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/status"
|
||||
@ -29,62 +27,6 @@ import (
|
||||
"github.com/zitadel/zitadel/pkg/grpc/user/v2"
|
||||
)
|
||||
|
||||
var (
|
||||
CTX context.Context
|
||||
IAMOwnerCTX context.Context
|
||||
Instance *integration.Instance
|
||||
Client session.SessionServiceClient
|
||||
User *user.AddHumanUserResponse
|
||||
DeactivatedUser *user.AddHumanUserResponse
|
||||
LockedUser *user.AddHumanUserResponse
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
os.Exit(func() int {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Minute)
|
||||
defer cancel()
|
||||
|
||||
Instance = integration.NewInstance(ctx)
|
||||
Client = Instance.Client.SessionV2beta
|
||||
|
||||
CTX = Instance.WithAuthorization(ctx, integration.UserTypeOrgOwner)
|
||||
IAMOwnerCTX = Instance.WithAuthorization(ctx, integration.UserTypeIAMOwner)
|
||||
User = createFullUser(CTX)
|
||||
DeactivatedUser = createDeactivatedUser(CTX)
|
||||
LockedUser = createLockedUser(CTX)
|
||||
return m.Run()
|
||||
}())
|
||||
}
|
||||
|
||||
func createFullUser(ctx context.Context) *user.AddHumanUserResponse {
|
||||
userResp := Instance.CreateHumanUser(ctx)
|
||||
Instance.Client.UserV2.VerifyEmail(ctx, &user.VerifyEmailRequest{
|
||||
UserId: userResp.GetUserId(),
|
||||
VerificationCode: userResp.GetEmailCode(),
|
||||
})
|
||||
Instance.Client.UserV2.VerifyPhone(ctx, &user.VerifyPhoneRequest{
|
||||
UserId: userResp.GetUserId(),
|
||||
VerificationCode: userResp.GetPhoneCode(),
|
||||
})
|
||||
Instance.SetUserPassword(ctx, userResp.GetUserId(), integration.UserPassword, false)
|
||||
Instance.RegisterUserPasskey(ctx, userResp.GetUserId())
|
||||
return userResp
|
||||
}
|
||||
|
||||
func createDeactivatedUser(ctx context.Context) *user.AddHumanUserResponse {
|
||||
userResp := Instance.CreateHumanUser(ctx)
|
||||
_, err := Instance.Client.UserV2.DeactivateUser(ctx, &user.DeactivateUserRequest{UserId: userResp.GetUserId()})
|
||||
logging.OnError(err).Fatal("deactivate human user")
|
||||
return userResp
|
||||
}
|
||||
|
||||
func createLockedUser(ctx context.Context) *user.AddHumanUserResponse {
|
||||
userResp := Instance.CreateHumanUser(ctx)
|
||||
_, err := Instance.Client.UserV2.LockUser(ctx, &user.LockUserRequest{UserId: userResp.GetUserId()})
|
||||
logging.OnError(err).Fatal("lock human user")
|
||||
return userResp
|
||||
}
|
||||
|
||||
func verifyCurrentSession(t testing.TB, id, token string, sequence uint64, window time.Duration, metadata map[string][]byte, userAgent *session.UserAgent, expirationWindow time.Duration, userID string, factors ...wantFactor) *session.Session {
|
||||
t.Helper()
|
||||
require.NotEmpty(t, id)
|
||||
@ -96,15 +38,25 @@ func verifyCurrentSession(t testing.TB, id, token string, sequence uint64, windo
|
||||
})
|
||||
require.NoError(t, err)
|
||||
s := resp.GetSession()
|
||||
want := &session.Session{
|
||||
Id: id,
|
||||
Sequence: sequence,
|
||||
Metadata: metadata,
|
||||
UserAgent: userAgent,
|
||||
}
|
||||
verifySession(t, s, want, window, expirationWindow, userID, factors...)
|
||||
return s
|
||||
}
|
||||
|
||||
assert.Equal(t, id, s.GetId())
|
||||
func verifySession(t assert.TestingT, s *session.Session, want *session.Session, window time.Duration, expirationWindow time.Duration, userID string, factors ...wantFactor) {
|
||||
assert.Equal(t, want.Id, s.GetId())
|
||||
assert.WithinRange(t, s.GetCreationDate().AsTime(), time.Now().Add(-window), time.Now().Add(window))
|
||||
assert.WithinRange(t, s.GetChangeDate().AsTime(), time.Now().Add(-window), time.Now().Add(window))
|
||||
assert.Equal(t, sequence, s.GetSequence())
|
||||
assert.Equal(t, metadata, s.GetMetadata())
|
||||
assert.Equal(t, want.Sequence, s.GetSequence())
|
||||
assert.Equal(t, want.Metadata, s.GetMetadata())
|
||||
|
||||
if !proto.Equal(userAgent, s.GetUserAgent()) {
|
||||
t.Errorf("user agent =\n%v\nwant\n%v", s.GetUserAgent(), userAgent)
|
||||
if !proto.Equal(want.UserAgent, s.GetUserAgent()) {
|
||||
t.Errorf("user agent =\n%v\nwant\n%v", s.GetUserAgent(), want.UserAgent)
|
||||
}
|
||||
if expirationWindow == 0 {
|
||||
assert.Nil(t, s.GetExpirationDate())
|
||||
@ -113,7 +65,6 @@ func verifyCurrentSession(t testing.TB, id, token string, sequence uint64, windo
|
||||
}
|
||||
|
||||
verifyFactors(t, s.GetFactors(), window, userID, factors)
|
||||
return s
|
||||
}
|
||||
|
||||
type wantFactor int
|
||||
@ -129,7 +80,7 @@ const (
|
||||
wantOTPEmailFactor
|
||||
)
|
||||
|
||||
func verifyFactors(t testing.TB, factors *session.Factors, window time.Duration, userID string, want []wantFactor) {
|
||||
func verifyFactors(t assert.TestingT, factors *session.Factors, window time.Duration, userID string, want []wantFactor) {
|
||||
for _, w := range want {
|
||||
switch w {
|
||||
case wantUserFactor:
|
||||
@ -194,8 +145,15 @@ func TestServer_CreateSession(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "user agent",
|
||||
name: "full session",
|
||||
req: &session.CreateSessionRequest{
|
||||
Checks: &session.Checks{
|
||||
User: &session.CheckUser{
|
||||
Search: &session.CheckUser_UserId{
|
||||
UserId: User.GetUserId(),
|
||||
},
|
||||
},
|
||||
},
|
||||
Metadata: map[string][]byte{"foo": []byte("bar")},
|
||||
UserAgent: &session.UserAgent{
|
||||
FingerprintId: gu.Ptr("fingerPrintID"),
|
||||
@ -205,6 +163,7 @@ func TestServer_CreateSession(t *testing.T) {
|
||||
"foo": {Values: []string{"foo", "bar"}},
|
||||
},
|
||||
},
|
||||
Lifetime: durationpb.New(5 * time.Minute),
|
||||
},
|
||||
want: &session.CreateSessionResponse{
|
||||
Details: &object.Details{
|
||||
@ -212,14 +171,6 @@ func TestServer_CreateSession(t *testing.T) {
|
||||
ResourceOwner: Instance.ID(),
|
||||
},
|
||||
},
|
||||
wantUserAgent: &session.UserAgent{
|
||||
FingerprintId: gu.Ptr("fingerPrintID"),
|
||||
Ip: gu.Ptr("1.2.3.4"),
|
||||
Description: gu.Ptr("Description"),
|
||||
Header: map[string]*session.UserAgent_HeaderValues{
|
||||
"foo": {Values: []string{"foo", "bar"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "negative lifetime",
|
||||
@ -229,40 +180,6 @@ func TestServer_CreateSession(t *testing.T) {
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "lifetime",
|
||||
req: &session.CreateSessionRequest{
|
||||
Metadata: map[string][]byte{"foo": []byte("bar")},
|
||||
Lifetime: durationpb.New(5 * time.Minute),
|
||||
},
|
||||
want: &session.CreateSessionResponse{
|
||||
Details: &object.Details{
|
||||
ChangeDate: timestamppb.Now(),
|
||||
ResourceOwner: Instance.ID(),
|
||||
},
|
||||
},
|
||||
wantExpirationWindow: 5 * time.Minute,
|
||||
},
|
||||
{
|
||||
name: "with user",
|
||||
req: &session.CreateSessionRequest{
|
||||
Checks: &session.Checks{
|
||||
User: &session.CheckUser{
|
||||
Search: &session.CheckUser_UserId{
|
||||
UserId: User.GetUserId(),
|
||||
},
|
||||
},
|
||||
},
|
||||
Metadata: map[string][]byte{"foo": []byte("bar")},
|
||||
},
|
||||
want: &session.CreateSessionResponse{
|
||||
Details: &object.Details{
|
||||
ChangeDate: timestamppb.Now(),
|
||||
ResourceOwner: Instance.ID(),
|
||||
},
|
||||
},
|
||||
wantFactors: []wantFactor{wantUserFactor},
|
||||
},
|
||||
{
|
||||
name: "deactivated user",
|
||||
req: &session.CreateSessionRequest{
|
||||
@ -340,8 +257,6 @@ func TestServer_CreateSession(t *testing.T) {
|
||||
}
|
||||
require.NoError(t, err)
|
||||
integration.AssertDetails(t, tt.want, got)
|
||||
|
||||
verifyCurrentSession(t, got.GetSessionId(), got.GetSessionToken(), got.GetDetails().GetSequence(), time.Minute, tt.req.GetMetadata(), tt.wantUserAgent, tt.wantExpirationWindow, User.GetUserId(), tt.wantFactors...)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -459,6 +459,10 @@ func prepareSessionsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBui
|
||||
SessionColumnOTPSMSCheckedAt.identifier(),
|
||||
SessionColumnOTPEmailCheckedAt.identifier(),
|
||||
SessionColumnMetadata.identifier(),
|
||||
SessionColumnUserAgentFingerprintID.identifier(),
|
||||
SessionColumnUserAgentIP.identifier(),
|
||||
SessionColumnUserAgentDescription.identifier(),
|
||||
SessionColumnUserAgentHeader.identifier(),
|
||||
SessionColumnExpiration.identifier(),
|
||||
countColumn.identifier(),
|
||||
).From(sessionsTable.identifier()).
|
||||
@ -485,6 +489,8 @@ func prepareSessionsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBui
|
||||
otpSMSCheckedAt sql.NullTime
|
||||
otpEmailCheckedAt sql.NullTime
|
||||
metadata database.Map[[]byte]
|
||||
userAgentIP sql.NullString
|
||||
userAgentHeader database.Map[[]string]
|
||||
expiration sql.NullTime
|
||||
)
|
||||
|
||||
@ -509,6 +515,10 @@ func prepareSessionsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBui
|
||||
&otpSMSCheckedAt,
|
||||
&otpEmailCheckedAt,
|
||||
&metadata,
|
||||
&session.UserAgent.FingerprintID,
|
||||
&userAgentIP,
|
||||
&session.UserAgent.Description,
|
||||
&userAgentHeader,
|
||||
&expiration,
|
||||
&sessions.Count,
|
||||
)
|
||||
@ -529,6 +539,10 @@ func prepareSessionsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBui
|
||||
session.OTPSMSFactor.OTPCheckedAt = otpSMSCheckedAt.Time
|
||||
session.OTPEmailFactor.OTPCheckedAt = otpEmailCheckedAt.Time
|
||||
session.Metadata = metadata
|
||||
session.UserAgent.Header = http.Header(userAgentHeader)
|
||||
if userAgentIP.Valid {
|
||||
session.UserAgent.IP = net.ParseIP(userAgentIP.String)
|
||||
}
|
||||
session.Expiration = expiration.Time
|
||||
|
||||
sessions.Sessions = append(sessions.Sessions, session)
|
||||
|
@ -71,6 +71,10 @@ var (
|
||||
` projections.sessions8.otp_sms_checked_at,` +
|
||||
` projections.sessions8.otp_email_checked_at,` +
|
||||
` projections.sessions8.metadata,` +
|
||||
` projections.sessions8.user_agent_fingerprint_id,` +
|
||||
` projections.sessions8.user_agent_ip,` +
|
||||
` projections.sessions8.user_agent_description,` +
|
||||
` projections.sessions8.user_agent_header,` +
|
||||
` projections.sessions8.expiration,` +
|
||||
` COUNT(*) OVER ()` +
|
||||
` FROM projections.sessions8` +
|
||||
@ -129,6 +133,10 @@ var (
|
||||
"otp_sms_checked_at",
|
||||
"otp_email_checked_at",
|
||||
"metadata",
|
||||
"user_agent_fingerprint_id",
|
||||
"user_agent_ip",
|
||||
"user_agent_description",
|
||||
"user_agent_header",
|
||||
"expiration",
|
||||
"count",
|
||||
}
|
||||
@ -186,6 +194,10 @@ func Test_SessionsPrepare(t *testing.T) {
|
||||
testNow,
|
||||
testNow,
|
||||
[]byte(`{"key": "dmFsdWU="}`),
|
||||
"fingerPrintID",
|
||||
"1.2.3.4",
|
||||
"agentDescription",
|
||||
[]byte(`{"foo":["foo","bar"]}`),
|
||||
testNow,
|
||||
},
|
||||
},
|
||||
@ -233,6 +245,12 @@ func Test_SessionsPrepare(t *testing.T) {
|
||||
Metadata: map[string][]byte{
|
||||
"key": []byte("value"),
|
||||
},
|
||||
UserAgent: domain.UserAgent{
|
||||
FingerprintID: gu.Ptr("fingerPrintID"),
|
||||
IP: net.IPv4(1, 2, 3, 4),
|
||||
Description: gu.Ptr("agentDescription"),
|
||||
Header: http.Header{"foo": []string{"foo", "bar"}},
|
||||
},
|
||||
Expiration: testNow,
|
||||
},
|
||||
},
|
||||
@ -267,6 +285,10 @@ func Test_SessionsPrepare(t *testing.T) {
|
||||
testNow,
|
||||
testNow,
|
||||
[]byte(`{"key": "dmFsdWU="}`),
|
||||
"fingerPrintID",
|
||||
"1.2.3.4",
|
||||
"agentDescription",
|
||||
[]byte(`{"foo":["foo","bar"]}`),
|
||||
testNow,
|
||||
},
|
||||
{
|
||||
@ -290,6 +312,10 @@ func Test_SessionsPrepare(t *testing.T) {
|
||||
testNow,
|
||||
testNow,
|
||||
[]byte(`{"key": "dmFsdWU="}`),
|
||||
"fingerPrintID",
|
||||
"1.2.3.4",
|
||||
"agentDescription",
|
||||
[]byte(`{"foo":["foo","bar"]}`),
|
||||
testNow,
|
||||
},
|
||||
},
|
||||
@ -337,6 +363,12 @@ func Test_SessionsPrepare(t *testing.T) {
|
||||
Metadata: map[string][]byte{
|
||||
"key": []byte("value"),
|
||||
},
|
||||
UserAgent: domain.UserAgent{
|
||||
FingerprintID: gu.Ptr("fingerPrintID"),
|
||||
IP: net.IPv4(1, 2, 3, 4),
|
||||
Description: gu.Ptr("agentDescription"),
|
||||
Header: http.Header{"foo": []string{"foo", "bar"}},
|
||||
},
|
||||
Expiration: testNow,
|
||||
},
|
||||
{
|
||||
@ -376,6 +408,12 @@ func Test_SessionsPrepare(t *testing.T) {
|
||||
Metadata: map[string][]byte{
|
||||
"key": []byte("value"),
|
||||
},
|
||||
UserAgent: domain.UserAgent{
|
||||
FingerprintID: gu.Ptr("fingerPrintID"),
|
||||
IP: net.IPv4(1, 2, 3, 4),
|
||||
Description: gu.Ptr("agentDescription"),
|
||||
Header: http.Header{"foo": []string{"foo", "bar"}},
|
||||
},
|
||||
Expiration: testNow,
|
||||
},
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user