mirror of
https://github.com/zitadel/zitadel.git
synced 2025-07-30 09:43:42 +00:00
feat: allow session deletion without session token (#6889)
* fix: add resource owner of user and change the one of session to instance * use user resource owner from session projection * fix session permission check * integration tests and fixes * update api docs
This commit is contained in:
parent
0948a0b9ae
commit
2e8c3b5a53
@ -953,6 +953,7 @@ InternalAuthZ:
|
|||||||
- "project.grant.member.delete"
|
- "project.grant.member.delete"
|
||||||
- "events.read"
|
- "events.read"
|
||||||
- "milestones.read"
|
- "milestones.read"
|
||||||
|
- "session.delete"
|
||||||
- Role: "IAM_OWNER_VIEWER"
|
- Role: "IAM_OWNER_VIEWER"
|
||||||
Permissions:
|
Permissions:
|
||||||
- "iam.read"
|
- "iam.read"
|
||||||
@ -1030,6 +1031,7 @@ InternalAuthZ:
|
|||||||
- "project.grant.member.read"
|
- "project.grant.member.read"
|
||||||
- "project.grant.member.write"
|
- "project.grant.member.write"
|
||||||
- "project.grant.member.delete"
|
- "project.grant.member.delete"
|
||||||
|
- "session.delete"
|
||||||
- Role: "IAM_USER_MANAGER"
|
- Role: "IAM_USER_MANAGER"
|
||||||
Permissions:
|
Permissions:
|
||||||
- "org.read"
|
- "org.read"
|
||||||
@ -1053,6 +1055,7 @@ InternalAuthZ:
|
|||||||
- "project.grant.write"
|
- "project.grant.write"
|
||||||
- "project.grant.delete"
|
- "project.grant.delete"
|
||||||
- "project.grant.member.read"
|
- "project.grant.member.read"
|
||||||
|
- "session.delete"
|
||||||
- Role: "ORG_OWNER"
|
- Role: "ORG_OWNER"
|
||||||
Permissions:
|
Permissions:
|
||||||
- "org.read"
|
- "org.read"
|
||||||
@ -1102,6 +1105,7 @@ InternalAuthZ:
|
|||||||
- "project.grant.member.read"
|
- "project.grant.member.read"
|
||||||
- "project.grant.member.write"
|
- "project.grant.member.write"
|
||||||
- "project.grant.member.delete"
|
- "project.grant.member.delete"
|
||||||
|
- "session.delete"
|
||||||
- Role: "ORG_USER_MANAGER"
|
- Role: "ORG_USER_MANAGER"
|
||||||
Permissions:
|
Permissions:
|
||||||
- "org.read"
|
- "org.read"
|
||||||
@ -1116,6 +1120,7 @@ InternalAuthZ:
|
|||||||
- "policy.read"
|
- "policy.read"
|
||||||
- "project.read"
|
- "project.read"
|
||||||
- "project.role.read"
|
- "project.role.read"
|
||||||
|
- "session.delete"
|
||||||
- Role: "ORG_OWNER_VIEWER"
|
- Role: "ORG_OWNER_VIEWER"
|
||||||
Permissions:
|
Permissions:
|
||||||
- "org.read"
|
- "org.read"
|
||||||
|
@ -355,7 +355,7 @@ func (s *Server) checksToCommand(ctx context.Context, checks *session.Checks) ([
|
|||||||
|
|
||||||
// trigger activity log for session for user
|
// trigger activity log for session for user
|
||||||
activity.Trigger(ctx, user.ResourceOwner, user.ID, activity.SessionAPI)
|
activity.Trigger(ctx, user.ResourceOwner, user.ID, activity.SessionAPI)
|
||||||
sessionChecks = append(sessionChecks, command.CheckUser(user.ID))
|
sessionChecks = append(sessionChecks, command.CheckUser(user.ID, user.ResourceOwner))
|
||||||
}
|
}
|
||||||
if password := checks.GetPassword(); password != nil {
|
if password := checks.GetPassword(); password != nil {
|
||||||
sessionChecks = append(sessionChecks, command.CheckPassword(password.GetPassword()))
|
sessionChecks = append(sessionChecks, command.CheckPassword(password.GetPassword()))
|
||||||
|
@ -158,7 +158,7 @@ func TestServer_CreateSession(t *testing.T) {
|
|||||||
},
|
},
|
||||||
want: &session.CreateSessionResponse{
|
want: &session.CreateSessionResponse{
|
||||||
Details: &object.Details{
|
Details: &object.Details{
|
||||||
ResourceOwner: Tester.Organisation.ID,
|
ResourceOwner: Tester.Instance.InstanceID(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -177,7 +177,7 @@ func TestServer_CreateSession(t *testing.T) {
|
|||||||
},
|
},
|
||||||
want: &session.CreateSessionResponse{
|
want: &session.CreateSessionResponse{
|
||||||
Details: &object.Details{
|
Details: &object.Details{
|
||||||
ResourceOwner: Tester.Organisation.ID,
|
ResourceOwner: Tester.Instance.InstanceID(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantUserAgent: &session.UserAgent{
|
wantUserAgent: &session.UserAgent{
|
||||||
@ -205,7 +205,7 @@ func TestServer_CreateSession(t *testing.T) {
|
|||||||
},
|
},
|
||||||
want: &session.CreateSessionResponse{
|
want: &session.CreateSessionResponse{
|
||||||
Details: &object.Details{
|
Details: &object.Details{
|
||||||
ResourceOwner: Tester.Organisation.ID,
|
ResourceOwner: Tester.Instance.InstanceID(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantExpirationWindow: 5 * time.Minute,
|
wantExpirationWindow: 5 * time.Minute,
|
||||||
@ -224,7 +224,7 @@ func TestServer_CreateSession(t *testing.T) {
|
|||||||
},
|
},
|
||||||
want: &session.CreateSessionResponse{
|
want: &session.CreateSessionResponse{
|
||||||
Details: &object.Details{
|
Details: &object.Details{
|
||||||
ResourceOwner: Tester.Organisation.ID,
|
ResourceOwner: Tester.Instance.InstanceID(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantFactors: []wantFactor{wantUserFactor},
|
wantFactors: []wantFactor{wantUserFactor},
|
||||||
@ -660,6 +660,77 @@ func TestServer_SetSession_expired(t *testing.T) {
|
|||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestServer_DeleteSession_token(t *testing.T) {
|
||||||
|
createResp, err := Client.CreateSession(CTX, &session.CreateSessionRequest{})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
_, err = Client.DeleteSession(CTX, &session.DeleteSessionRequest{
|
||||||
|
SessionId: createResp.GetSessionId(),
|
||||||
|
SessionToken: gu.Ptr("invalid"),
|
||||||
|
})
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
_, err = Client.DeleteSession(CTX, &session.DeleteSessionRequest{
|
||||||
|
SessionId: createResp.GetSessionId(),
|
||||||
|
SessionToken: gu.Ptr(createResp.GetSessionToken()),
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestServer_DeleteSession_own_session(t *testing.T) {
|
||||||
|
// create two users for the test and a session each to get tokens for authorization
|
||||||
|
user1 := Tester.CreateHumanUser(CTX)
|
||||||
|
Tester.SetUserPassword(CTX, user1.GetUserId(), integration.UserPassword)
|
||||||
|
_, token1, _, _ := Tester.CreatePasswordSession(t, CTX, user1.GetUserId(), integration.UserPassword)
|
||||||
|
|
||||||
|
user2 := Tester.CreateHumanUser(CTX)
|
||||||
|
Tester.SetUserPassword(CTX, user2.GetUserId(), integration.UserPassword)
|
||||||
|
_, token2, _, _ := Tester.CreatePasswordSession(t, CTX, user2.GetUserId(), integration.UserPassword)
|
||||||
|
|
||||||
|
// create a new session for the first user
|
||||||
|
createResp, err := Client.CreateSession(CTX, &session.CreateSessionRequest{
|
||||||
|
Checks: &session.Checks{
|
||||||
|
User: &session.CheckUser{
|
||||||
|
Search: &session.CheckUser_UserId{
|
||||||
|
UserId: user1.GetUserId(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// delete the new (user1) session must not be possible with user (has no permission)
|
||||||
|
_, err = Client.DeleteSession(Tester.WithAuthorizationToken(context.Background(), token2), &session.DeleteSessionRequest{
|
||||||
|
SessionId: createResp.GetSessionId(),
|
||||||
|
})
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
// delete the new (user1) session by himself
|
||||||
|
_, err = Client.DeleteSession(Tester.WithAuthorizationToken(context.Background(), token1), &session.DeleteSessionRequest{
|
||||||
|
SessionId: createResp.GetSessionId(),
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestServer_DeleteSession_with_permission(t *testing.T) {
|
||||||
|
createResp, err := Client.CreateSession(CTX, &session.CreateSessionRequest{
|
||||||
|
Checks: &session.Checks{
|
||||||
|
User: &session.CheckUser{
|
||||||
|
Search: &session.CheckUser_UserId{
|
||||||
|
UserId: User.GetUserId(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// delete the new session by ORG_OWNER
|
||||||
|
_, err = Client.DeleteSession(Tester.WithAuthorization(context.Background(), integration.OrgOwner), &session.DeleteSessionRequest{
|
||||||
|
SessionId: createResp.GetSessionId(),
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
func Test_ZITADEL_API_missing_authentication(t *testing.T) {
|
func Test_ZITADEL_API_missing_authentication(t *testing.T) {
|
||||||
// create new, empty session
|
// create new, empty session
|
||||||
createResp, err := Client.CreateSession(CTX, &session.CreateSessionRequest{})
|
createResp, err := Client.CreateSession(CTX, &session.CreateSessionRequest{})
|
||||||
|
@ -90,7 +90,7 @@ func (c *Commands) LinkSessionToAuthRequest(ctx context.Context, id, sessionID,
|
|||||||
if checkLoginClient && authz.GetCtxData(ctx).UserID != writeModel.LoginClient {
|
if checkLoginClient && authz.GetCtxData(ctx).UserID != writeModel.LoginClient {
|
||||||
return nil, nil, errors.ThrowPermissionDenied(nil, "COMMAND-rai9Y", "Errors.AuthRequest.WrongLoginClient")
|
return nil, nil, errors.ThrowPermissionDenied(nil, "COMMAND-rai9Y", "Errors.AuthRequest.WrongLoginClient")
|
||||||
}
|
}
|
||||||
sessionWriteModel := NewSessionWriteModel(sessionID, authz.GetCtxData(ctx).OrgID)
|
sessionWriteModel := NewSessionWriteModel(sessionID, authz.GetInstance(ctx).InstanceID())
|
||||||
err = c.eventstore.FilterToQueryReducer(ctx, sessionWriteModel)
|
err = c.eventstore.FilterToQueryReducer(ctx, sessionWriteModel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
@ -98,7 +98,7 @@ func (c *Commands) LinkSessionToAuthRequest(ctx context.Context, id, sessionID,
|
|||||||
if err = sessionWriteModel.CheckIsActive(); err != nil {
|
if err = sessionWriteModel.CheckIsActive(); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
if err := c.sessionPermission(ctx, sessionWriteModel, sessionToken, domain.PermissionSessionWrite); err != nil {
|
if err := c.sessionTokenVerifier(ctx, sessionToken, sessionWriteModel.AggregateID, sessionWriteModel.TokenID); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,9 +164,8 @@ func TestCommands_AddAuthRequest(t *testing.T) {
|
|||||||
func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
||||||
mockCtx := authz.NewMockContext("instanceID", "orgID", "loginClient")
|
mockCtx := authz.NewMockContext("instanceID", "orgID", "loginClient")
|
||||||
type fields struct {
|
type fields struct {
|
||||||
eventstore *eventstore.Eventstore
|
eventstore *eventstore.Eventstore
|
||||||
tokenVerifier func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error)
|
tokenVerifier func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error)
|
||||||
checkPermission domain.PermissionCheck
|
|
||||||
}
|
}
|
||||||
type args struct {
|
type args struct {
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
@ -192,10 +191,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
|||||||
eventstore: eventstoreExpect(t,
|
eventstore: eventstoreExpect(t,
|
||||||
expectFilter(),
|
expectFilter(),
|
||||||
),
|
),
|
||||||
tokenVerifier: func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error) {
|
tokenVerifier: newMockTokenVerifierValid(),
|
||||||
return nil
|
|
||||||
},
|
|
||||||
checkPermission: newMockPermissionCheckNotAllowed(),
|
|
||||||
},
|
},
|
||||||
args{
|
args{
|
||||||
ctx: mockCtx,
|
ctx: mockCtx,
|
||||||
@ -235,10 +231,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
tokenVerifier: func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error) {
|
tokenVerifier: newMockTokenVerifierValid(),
|
||||||
return nil
|
|
||||||
},
|
|
||||||
checkPermission: newMockPermissionCheckAllowed(),
|
|
||||||
},
|
},
|
||||||
args{
|
args{
|
||||||
ctx: mockCtx,
|
ctx: mockCtx,
|
||||||
@ -274,10 +267,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
tokenVerifier: func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error) {
|
tokenVerifier: newMockTokenVerifierValid(),
|
||||||
return nil
|
|
||||||
},
|
|
||||||
checkPermission: newMockPermissionCheckAllowed(),
|
|
||||||
},
|
},
|
||||||
args{
|
args{
|
||||||
ctx: authz.NewMockContext("instanceID", "orgID", "wrongLoginClient"),
|
ctx: authz.NewMockContext("instanceID", "orgID", "wrongLoginClient"),
|
||||||
@ -316,10 +306,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
|||||||
),
|
),
|
||||||
expectFilter(),
|
expectFilter(),
|
||||||
),
|
),
|
||||||
tokenVerifier: func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error) {
|
tokenVerifier: newMockTokenVerifierValid(),
|
||||||
return nil
|
|
||||||
},
|
|
||||||
checkPermission: newMockPermissionCheckNotAllowed(),
|
|
||||||
},
|
},
|
||||||
args{
|
args{
|
||||||
ctx: mockCtx,
|
ctx: mockCtx,
|
||||||
@ -357,7 +344,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
|||||||
expectFilter(
|
expectFilter(
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
session.NewAddedEvent(mockCtx,
|
session.NewAddedEvent(mockCtx,
|
||||||
&session.NewAggregate("sessionID", "org1").Aggregate,
|
&session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
&domain.UserAgent{
|
&domain.UserAgent{
|
||||||
FingerprintID: gu.Ptr("fp1"),
|
FingerprintID: gu.Ptr("fp1"),
|
||||||
IP: net.ParseIP("1.2.3.4"),
|
IP: net.ParseIP("1.2.3.4"),
|
||||||
@ -366,15 +353,15 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
|||||||
},
|
},
|
||||||
)),
|
)),
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
session.NewUserCheckedEvent(mockCtx, &session.NewAggregate("sessionID", "org1").Aggregate,
|
session.NewUserCheckedEvent(mockCtx, &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
"userID", testNow.Add(-5*time.Minute)),
|
"userID", "org1", testNow.Add(-5*time.Minute)),
|
||||||
),
|
),
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
session.NewPasswordCheckedEvent(mockCtx, &session.NewAggregate("sessionID", "org1").Aggregate,
|
session.NewPasswordCheckedEvent(mockCtx, &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
testNow.Add(-5*time.Minute)),
|
testNow.Add(-5*time.Minute)),
|
||||||
),
|
),
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
session.NewLifetimeSetEvent(mockCtx, &session.NewAggregate("sessionID", "org1").Aggregate,
|
session.NewLifetimeSetEvent(mockCtx, &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
2*time.Minute),
|
2*time.Minute),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -390,57 +377,6 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
|||||||
wantErr: caos_errs.ThrowPreconditionFailed(nil, "COMMAND-Hkl3d", "Errors.Session.Expired"),
|
wantErr: caos_errs.ThrowPreconditionFailed(nil, "COMMAND-Hkl3d", "Errors.Session.Expired"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"missing permission",
|
|
||||||
fields{
|
|
||||||
eventstore: eventstoreExpect(t,
|
|
||||||
expectFilter(
|
|
||||||
eventFromEventPusher(
|
|
||||||
authrequest.NewAddedEvent(mockCtx, &authrequest.NewAggregate("V2_id", "instanceID").Aggregate,
|
|
||||||
"loginClient",
|
|
||||||
"clientID",
|
|
||||||
"redirectURI",
|
|
||||||
"state",
|
|
||||||
"nonce",
|
|
||||||
[]string{"openid"},
|
|
||||||
[]string{"audience"},
|
|
||||||
domain.OIDCResponseTypeCode,
|
|
||||||
nil,
|
|
||||||
nil,
|
|
||||||
nil,
|
|
||||||
nil,
|
|
||||||
nil,
|
|
||||||
nil,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
expectFilter(
|
|
||||||
eventFromEventPusher(
|
|
||||||
session.NewAddedEvent(mockCtx,
|
|
||||||
&session.NewAggregate("sessionID", "org1").Aggregate,
|
|
||||||
&domain.UserAgent{
|
|
||||||
FingerprintID: gu.Ptr("fp1"),
|
|
||||||
IP: net.ParseIP("1.2.3.4"),
|
|
||||||
Description: gu.Ptr("firefox"),
|
|
||||||
Header: http.Header{"foo": []string{"bar"}},
|
|
||||||
},
|
|
||||||
)),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
tokenVerifier: func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error) {
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
checkPermission: newMockPermissionCheckNotAllowed(),
|
|
||||||
},
|
|
||||||
args{
|
|
||||||
ctx: mockCtx,
|
|
||||||
id: "V2_id",
|
|
||||||
sessionID: "sessionID",
|
|
||||||
},
|
|
||||||
res{
|
|
||||||
wantErr: caos_errs.ThrowPermissionDenied(nil, "AUTHZ-HKJD33", "Errors.PermissionDenied"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"invalid session token",
|
"invalid session token",
|
||||||
fields{
|
fields{
|
||||||
@ -468,7 +404,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
|||||||
expectFilter(
|
expectFilter(
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
session.NewAddedEvent(mockCtx,
|
session.NewAddedEvent(mockCtx,
|
||||||
&session.NewAggregate("sessionID", "org1").Aggregate,
|
&session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
&domain.UserAgent{
|
&domain.UserAgent{
|
||||||
FingerprintID: gu.Ptr("fp1"),
|
FingerprintID: gu.Ptr("fp1"),
|
||||||
IP: net.ParseIP("1.2.3.4"),
|
IP: net.ParseIP("1.2.3.4"),
|
||||||
@ -478,9 +414,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
|||||||
)),
|
)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
tokenVerifier: func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error) {
|
tokenVerifier: newMockTokenVerifierInvalid(),
|
||||||
return caos_errs.ThrowPermissionDenied(nil, "COMMAND-sGr42", "Errors.Session.Token.Invalid")
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
args{
|
args{
|
||||||
ctx: mockCtx,
|
ctx: mockCtx,
|
||||||
@ -519,7 +453,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
|||||||
expectFilter(
|
expectFilter(
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
session.NewAddedEvent(mockCtx,
|
session.NewAddedEvent(mockCtx,
|
||||||
&session.NewAggregate("sessionID", "org1").Aggregate,
|
&session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
&domain.UserAgent{
|
&domain.UserAgent{
|
||||||
FingerprintID: gu.Ptr("fp1"),
|
FingerprintID: gu.Ptr("fp1"),
|
||||||
IP: net.ParseIP("1.2.3.4"),
|
IP: net.ParseIP("1.2.3.4"),
|
||||||
@ -528,15 +462,15 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
|||||||
},
|
},
|
||||||
)),
|
)),
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
session.NewUserCheckedEvent(mockCtx, &session.NewAggregate("sessionID", "org1").Aggregate,
|
session.NewUserCheckedEvent(mockCtx, &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
"userID", testNow),
|
"userID", "org1", testNow),
|
||||||
),
|
),
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
session.NewPasswordCheckedEvent(mockCtx, &session.NewAggregate("sessionID", "org1").Aggregate,
|
session.NewPasswordCheckedEvent(mockCtx, &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
testNow),
|
testNow),
|
||||||
),
|
),
|
||||||
eventFromEventPusherWithCreationDateNow(
|
eventFromEventPusherWithCreationDateNow(
|
||||||
session.NewLifetimeSetEvent(mockCtx, &session.NewAggregate("sessionID", "org1").Aggregate,
|
session.NewLifetimeSetEvent(mockCtx, &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
2*time.Minute),
|
2*time.Minute),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -549,10 +483,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
tokenVerifier: func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error) {
|
tokenVerifier: newMockTokenVerifierValid(),
|
||||||
return nil
|
|
||||||
},
|
|
||||||
checkPermission: newMockPermissionCheckAllowed(),
|
|
||||||
},
|
},
|
||||||
args{
|
args{
|
||||||
ctx: mockCtx,
|
ctx: mockCtx,
|
||||||
@ -607,7 +538,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
|||||||
expectFilter(
|
expectFilter(
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
session.NewAddedEvent(mockCtx,
|
session.NewAddedEvent(mockCtx,
|
||||||
&session.NewAggregate("sessionID", "org1").Aggregate,
|
&session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
&domain.UserAgent{
|
&domain.UserAgent{
|
||||||
FingerprintID: gu.Ptr("fp1"),
|
FingerprintID: gu.Ptr("fp1"),
|
||||||
IP: net.ParseIP("1.2.3.4"),
|
IP: net.ParseIP("1.2.3.4"),
|
||||||
@ -616,15 +547,15 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
|||||||
},
|
},
|
||||||
)),
|
)),
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
session.NewUserCheckedEvent(mockCtx, &session.NewAggregate("sessionID", "org1").Aggregate,
|
session.NewUserCheckedEvent(mockCtx, &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
"userID", testNow),
|
"userID", "org1", testNow),
|
||||||
),
|
),
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
session.NewPasswordCheckedEvent(mockCtx, &session.NewAggregate("sessionID", "org1").Aggregate,
|
session.NewPasswordCheckedEvent(mockCtx, &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
testNow),
|
testNow),
|
||||||
),
|
),
|
||||||
eventFromEventPusherWithCreationDateNow(
|
eventFromEventPusherWithCreationDateNow(
|
||||||
session.NewLifetimeSetEvent(mockCtx, &session.NewAggregate("sessionID", "org1").Aggregate,
|
session.NewLifetimeSetEvent(mockCtx, &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
2*time.Minute),
|
2*time.Minute),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -637,10 +568,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
tokenVerifier: func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error) {
|
tokenVerifier: newMockTokenVerifierValid(),
|
||||||
return nil
|
|
||||||
},
|
|
||||||
checkPermission: newMockPermissionCheckAllowed(),
|
|
||||||
},
|
},
|
||||||
args{
|
args{
|
||||||
ctx: authz.NewMockContext("instanceID", "orgID", "loginClient"),
|
ctx: authz.NewMockContext("instanceID", "orgID", "loginClient"),
|
||||||
@ -675,7 +603,6 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
|
|||||||
c := &Commands{
|
c := &Commands{
|
||||||
eventstore: tt.fields.eventstore,
|
eventstore: tt.fields.eventstore,
|
||||||
sessionTokenVerifier: tt.fields.tokenVerifier,
|
sessionTokenVerifier: tt.fields.tokenVerifier,
|
||||||
checkPermission: tt.fields.checkPermission,
|
|
||||||
}
|
}
|
||||||
details, got, err := c.LinkSessionToAuthRequest(tt.args.ctx, tt.args.id, tt.args.sessionID, tt.args.sessionToken, tt.args.checkLoginClient)
|
details, got, err := c.LinkSessionToAuthRequest(tt.args.ctx, tt.args.id, tt.args.sessionID, tt.args.sessionToken, tt.args.checkLoginClient)
|
||||||
require.ErrorIs(t, err, tt.res.wantErr)
|
require.ErrorIs(t, err, tt.res.wantErr)
|
||||||
|
@ -241,6 +241,17 @@ func newMockPermissionCheckNotAllowed() domain.PermissionCheck {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newMockTokenVerifierValid() func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error) {
|
||||||
|
return func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func newMockTokenVerifierInvalid() func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error) {
|
||||||
|
return func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error) {
|
||||||
|
return errors.ThrowPermissionDenied(nil, "COMMAND-sGr42", "Errors.Session.Token.Invalid")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type plainHasher struct {
|
type plainHasher struct {
|
||||||
x string // arbitrary info that triggers update when different from encoding
|
x string // arbitrary info that triggers update when different from encoding
|
||||||
}
|
}
|
||||||
|
@ -153,7 +153,7 @@ func (c *Commands) newOIDCSessionAddEvents(ctx context.Context, authRequestID st
|
|||||||
if err = authRequestWriteModel.CheckAuthenticated(); err != nil {
|
if err = authRequestWriteModel.CheckAuthenticated(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
sessionWriteModel := NewSessionWriteModel(authRequestWriteModel.SessionID, authz.GetCtxData(ctx).OrgID)
|
sessionWriteModel := NewSessionWriteModel(authRequestWriteModel.SessionID, authz.GetInstance(ctx).InstanceID())
|
||||||
err = c.eventstore.FilterToQueryReducer(ctx, sessionWriteModel)
|
err = c.eventstore.FilterToQueryReducer(ctx, sessionWriteModel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -166,7 +166,7 @@ func TestCommands_AddOIDCSessionAccessToken(t *testing.T) {
|
|||||||
expectFilter(
|
expectFilter(
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
session.NewAddedEvent(context.Background(),
|
session.NewAddedEvent(context.Background(),
|
||||||
&session.NewAggregate("sessionID", "org1").Aggregate,
|
&session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
&domain.UserAgent{
|
&domain.UserAgent{
|
||||||
FingerprintID: gu.Ptr("fp1"),
|
FingerprintID: gu.Ptr("fp1"),
|
||||||
IP: net.ParseIP("1.2.3.4"),
|
IP: net.ParseIP("1.2.3.4"),
|
||||||
@ -177,7 +177,7 @@ func TestCommands_AddOIDCSessionAccessToken(t *testing.T) {
|
|||||||
),
|
),
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
session.NewUserCheckedEvent(context.Background(), &session.NewAggregate("sessionID", "instanceID").Aggregate,
|
session.NewUserCheckedEvent(context.Background(), &session.NewAggregate("sessionID", "instanceID").Aggregate,
|
||||||
"userID", testNow),
|
"userID", "org1", testNow),
|
||||||
),
|
),
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
session.NewPasswordCheckedEvent(context.Background(), &session.NewAggregate("sessionID", "instanceID").Aggregate,
|
session.NewPasswordCheckedEvent(context.Background(), &session.NewAggregate("sessionID", "instanceID").Aggregate,
|
||||||
@ -367,7 +367,7 @@ func TestCommands_AddOIDCSessionRefreshAndAccessToken(t *testing.T) {
|
|||||||
expectFilter(
|
expectFilter(
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
session.NewAddedEvent(context.Background(),
|
session.NewAddedEvent(context.Background(),
|
||||||
&session.NewAggregate("sessionID", "org1").Aggregate,
|
&session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
&domain.UserAgent{
|
&domain.UserAgent{
|
||||||
FingerprintID: gu.Ptr("fp1"),
|
FingerprintID: gu.Ptr("fp1"),
|
||||||
IP: net.ParseIP("1.2.3.4"),
|
IP: net.ParseIP("1.2.3.4"),
|
||||||
@ -378,7 +378,7 @@ func TestCommands_AddOIDCSessionRefreshAndAccessToken(t *testing.T) {
|
|||||||
),
|
),
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
session.NewUserCheckedEvent(context.Background(), &session.NewAggregate("sessionID", "instanceID").Aggregate,
|
session.NewUserCheckedEvent(context.Background(), &session.NewAggregate("sessionID", "instanceID").Aggregate,
|
||||||
"userID", testNow),
|
"userID", "org1", testNow),
|
||||||
),
|
),
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
session.NewPasswordCheckedEvent(context.Background(), &session.NewAggregate("sessionID", "instanceID").Aggregate,
|
session.NewPasswordCheckedEvent(context.Background(), &session.NewAggregate("sessionID", "instanceID").Aggregate,
|
||||||
|
@ -55,12 +55,12 @@ func (c *Commands) NewSessionCommands(cmds []SessionCommand, session *SessionWri
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CheckUser defines a user check to be executed for a session update
|
// CheckUser defines a user check to be executed for a session update
|
||||||
func CheckUser(id string) SessionCommand {
|
func CheckUser(id string, resourceOwner string) SessionCommand {
|
||||||
return func(ctx context.Context, cmd *SessionCommands) error {
|
return func(ctx context.Context, cmd *SessionCommands) error {
|
||||||
if cmd.sessionWriteModel.UserID != "" && id != "" && cmd.sessionWriteModel.UserID != id {
|
if cmd.sessionWriteModel.UserID != "" && id != "" && cmd.sessionWriteModel.UserID != id {
|
||||||
return caos_errs.ThrowInvalidArgument(nil, "", "user change not possible")
|
return caos_errs.ThrowInvalidArgument(nil, "", "user change not possible")
|
||||||
}
|
}
|
||||||
return cmd.UserChecked(ctx, id, cmd.now())
|
return cmd.UserChecked(ctx, id, resourceOwner, cmd.now())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,10 +170,11 @@ func (s *SessionCommands) Start(ctx context.Context, userAgent *domain.UserAgent
|
|||||||
s.eventCommands = append(s.eventCommands, session.NewAddedEvent(ctx, s.sessionWriteModel.aggregate, userAgent))
|
s.eventCommands = append(s.eventCommands, session.NewAddedEvent(ctx, s.sessionWriteModel.aggregate, userAgent))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SessionCommands) UserChecked(ctx context.Context, userID string, checkedAt time.Time) error {
|
func (s *SessionCommands) UserChecked(ctx context.Context, userID, resourceOwner string, checkedAt time.Time) error {
|
||||||
s.eventCommands = append(s.eventCommands, session.NewUserCheckedEvent(ctx, s.sessionWriteModel.aggregate, userID, checkedAt))
|
s.eventCommands = append(s.eventCommands, session.NewUserCheckedEvent(ctx, s.sessionWriteModel.aggregate, userID, resourceOwner, checkedAt))
|
||||||
// set the userID so other checks can use it
|
// set the userID so other checks can use it
|
||||||
s.sessionWriteModel.UserID = userID
|
s.sessionWriteModel.UserID = userID
|
||||||
|
s.sessionWriteModel.UserResourceOwner = resourceOwner
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,7 +268,7 @@ func (s *SessionCommands) gethumanWriteModel(ctx context.Context) (*HumanWriteMo
|
|||||||
if s.sessionWriteModel.UserID == "" {
|
if s.sessionWriteModel.UserID == "" {
|
||||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-eeR2e", "Errors.User.UserIDMissing")
|
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-eeR2e", "Errors.User.UserIDMissing")
|
||||||
}
|
}
|
||||||
humanWriteModel := NewHumanWriteModel(s.sessionWriteModel.UserID, "")
|
humanWriteModel := NewHumanWriteModel(s.sessionWriteModel.UserID, s.sessionWriteModel.UserResourceOwner)
|
||||||
err := s.eventstore.FilterToQueryReducer(ctx, humanWriteModel)
|
err := s.eventstore.FilterToQueryReducer(ctx, humanWriteModel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -296,7 +297,7 @@ func (c *Commands) CreateSession(ctx context.Context, cmds []SessionCommand, met
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
sessionWriteModel := NewSessionWriteModel(sessionID, authz.GetCtxData(ctx).OrgID)
|
sessionWriteModel := NewSessionWriteModel(sessionID, authz.GetInstance(ctx).InstanceID())
|
||||||
err = c.eventstore.FilterToQueryReducer(ctx, sessionWriteModel)
|
err = c.eventstore.FilterToQueryReducer(ctx, sessionWriteModel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -307,12 +308,12 @@ func (c *Commands) CreateSession(ctx context.Context, cmds []SessionCommand, met
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Commands) UpdateSession(ctx context.Context, sessionID, sessionToken string, cmds []SessionCommand, metadata map[string][]byte, lifetime time.Duration) (set *SessionChanged, err error) {
|
func (c *Commands) UpdateSession(ctx context.Context, sessionID, sessionToken string, cmds []SessionCommand, metadata map[string][]byte, lifetime time.Duration) (set *SessionChanged, err error) {
|
||||||
sessionWriteModel := NewSessionWriteModel(sessionID, authz.GetCtxData(ctx).OrgID)
|
sessionWriteModel := NewSessionWriteModel(sessionID, authz.GetInstance(ctx).InstanceID())
|
||||||
err = c.eventstore.FilterToQueryReducer(ctx, sessionWriteModel)
|
err = c.eventstore.FilterToQueryReducer(ctx, sessionWriteModel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := c.sessionPermission(ctx, sessionWriteModel, sessionToken, domain.PermissionSessionWrite); err != nil {
|
if err := c.sessionTokenVerifier(ctx, sessionToken, sessionWriteModel.AggregateID, sessionWriteModel.TokenID); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
cmd := c.NewSessionCommands(cmds, sessionWriteModel)
|
cmd := c.NewSessionCommands(cmds, sessionWriteModel)
|
||||||
@ -328,12 +329,12 @@ func (c *Commands) TerminateSessionWithoutTokenCheck(ctx context.Context, sessio
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Commands) terminateSession(ctx context.Context, sessionID, sessionToken string, mustCheckToken bool) (*domain.ObjectDetails, error) {
|
func (c *Commands) terminateSession(ctx context.Context, sessionID, sessionToken string, mustCheckToken bool) (*domain.ObjectDetails, error) {
|
||||||
sessionWriteModel := NewSessionWriteModel(sessionID, "")
|
sessionWriteModel := NewSessionWriteModel(sessionID, authz.GetInstance(ctx).InstanceID())
|
||||||
if err := c.eventstore.FilterToQueryReducer(ctx, sessionWriteModel); err != nil {
|
if err := c.eventstore.FilterToQueryReducer(ctx, sessionWriteModel); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if mustCheckToken {
|
if mustCheckToken {
|
||||||
if err := c.sessionPermission(ctx, sessionWriteModel, sessionToken, domain.PermissionSessionDelete); err != nil {
|
if err := c.checkSessionTerminationPermission(ctx, sessionWriteModel, sessionToken); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -386,13 +387,17 @@ func (c *Commands) updateSession(ctx context.Context, checks *SessionCommands, m
|
|||||||
return changed, nil
|
return changed, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// sessionPermission will check that the provided sessionToken is correct or
|
// checkSessionTerminationPermission will check that the provided sessionToken is correct or
|
||||||
// if empty, check that the caller is granted the necessary permission
|
// if empty, check that the caller is either terminating the own session or
|
||||||
func (c *Commands) sessionPermission(ctx context.Context, sessionWriteModel *SessionWriteModel, sessionToken, permission string) (err error) {
|
// is granted the "session.delete" permission on the resource owner of the authenticated user.
|
||||||
if sessionToken == "" {
|
func (c *Commands) checkSessionTerminationPermission(ctx context.Context, model *SessionWriteModel, token string) error {
|
||||||
return c.checkPermission(ctx, permission, authz.GetCtxData(ctx).OrgID, sessionWriteModel.AggregateID)
|
if token != "" {
|
||||||
|
return c.sessionTokenVerifier(ctx, token, model.AggregateID, model.TokenID)
|
||||||
}
|
}
|
||||||
return c.sessionTokenVerifier(ctx, sessionToken, sessionWriteModel.AggregateID, sessionWriteModel.TokenID)
|
if model.UserID != "" && model.UserID == authz.GetCtxData(ctx).UserID {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return c.checkPermission(ctx, domain.PermissionSessionDelete, model.UserResourceOwner, model.UserID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func sessionTokenCreator(idGenerator id.Generator, sessionAlg crypto.EncryptionAlgorithm) func(sessionID string) (id string, token string, err error) {
|
func sessionTokenCreator(idGenerator id.Generator, sessionAlg crypto.EncryptionAlgorithm) func(sessionID string) (id string, token string, err error) {
|
||||||
|
@ -39,6 +39,7 @@ type SessionWriteModel struct {
|
|||||||
|
|
||||||
TokenID string
|
TokenID string
|
||||||
UserID string
|
UserID string
|
||||||
|
UserResourceOwner string
|
||||||
UserCheckedAt time.Time
|
UserCheckedAt time.Time
|
||||||
PasswordCheckedAt time.Time
|
PasswordCheckedAt time.Time
|
||||||
IntentCheckedAt time.Time
|
IntentCheckedAt time.Time
|
||||||
@ -58,14 +59,14 @@ type SessionWriteModel struct {
|
|||||||
aggregate *eventstore.Aggregate
|
aggregate *eventstore.Aggregate
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSessionWriteModel(sessionID string, resourceOwner string) *SessionWriteModel {
|
func NewSessionWriteModel(sessionID string, instanceID string) *SessionWriteModel {
|
||||||
return &SessionWriteModel{
|
return &SessionWriteModel{
|
||||||
WriteModel: eventstore.WriteModel{
|
WriteModel: eventstore.WriteModel{
|
||||||
AggregateID: sessionID,
|
AggregateID: sessionID,
|
||||||
ResourceOwner: resourceOwner,
|
ResourceOwner: instanceID,
|
||||||
},
|
},
|
||||||
Metadata: make(map[string][]byte),
|
Metadata: make(map[string][]byte),
|
||||||
aggregate: &session.NewAggregate(sessionID, resourceOwner).Aggregate,
|
aggregate: &session.NewAggregate(sessionID, instanceID).Aggregate,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,6 +142,7 @@ func (wm *SessionWriteModel) reduceAdded(e *session.AddedEvent) {
|
|||||||
|
|
||||||
func (wm *SessionWriteModel) reduceUserChecked(e *session.UserCheckedEvent) {
|
func (wm *SessionWriteModel) reduceUserChecked(e *session.UserCheckedEvent) {
|
||||||
wm.UserID = e.UserID
|
wm.UserID = e.UserID
|
||||||
|
wm.UserResourceOwner = e.UserResourceOwner
|
||||||
wm.UserCheckedAt = e.CheckedAt
|
wm.UserCheckedAt = e.CheckedAt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,7 +204,7 @@ func TestCommands_CreateSession(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
args{
|
args{
|
||||||
ctx: authz.NewMockContext("", "org1", ""),
|
ctx: authz.NewMockContext("instance1", "", ""),
|
||||||
userAgent: &domain.UserAgent{
|
userAgent: &domain.UserAgent{
|
||||||
FingerprintID: gu.Ptr("fp1"),
|
FingerprintID: gu.Ptr("fp1"),
|
||||||
IP: net.ParseIP("1.2.3.4"),
|
IP: net.ParseIP("1.2.3.4"),
|
||||||
@ -231,7 +231,7 @@ func TestCommands_CreateSession(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
args{
|
args{
|
||||||
ctx: authz.NewMockContext("", "org1", ""),
|
ctx: authz.NewMockContext("instance1", "", ""),
|
||||||
userAgent: &domain.UserAgent{
|
userAgent: &domain.UserAgent{
|
||||||
FingerprintID: gu.Ptr("fp1"),
|
FingerprintID: gu.Ptr("fp1"),
|
||||||
IP: net.ParseIP("1.2.3.4"),
|
IP: net.ParseIP("1.2.3.4"),
|
||||||
@ -244,7 +244,7 @@ func TestCommands_CreateSession(t *testing.T) {
|
|||||||
expectFilter(),
|
expectFilter(),
|
||||||
expectPush(
|
expectPush(
|
||||||
session.NewAddedEvent(context.Background(),
|
session.NewAddedEvent(context.Background(),
|
||||||
&session.NewAggregate("sessionID", "org1").Aggregate,
|
&session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
&domain.UserAgent{
|
&domain.UserAgent{
|
||||||
FingerprintID: gu.Ptr("fp1"),
|
FingerprintID: gu.Ptr("fp1"),
|
||||||
IP: net.ParseIP("1.2.3.4"),
|
IP: net.ParseIP("1.2.3.4"),
|
||||||
@ -252,15 +252,15 @@ func TestCommands_CreateSession(t *testing.T) {
|
|||||||
Header: http.Header{"foo": []string{"bar"}},
|
Header: http.Header{"foo": []string{"bar"}},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
session.NewLifetimeSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate, 10*time.Minute),
|
session.NewLifetimeSetEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate, 10*time.Minute),
|
||||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
"tokenID",
|
"tokenID",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
res{
|
res{
|
||||||
want: &SessionChanged{
|
want: &SessionChanged{
|
||||||
ObjectDetails: &domain.ObjectDetails{ResourceOwner: "org1"},
|
ObjectDetails: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
||||||
ID: "sessionID",
|
ID: "sessionID",
|
||||||
NewToken: "token",
|
NewToken: "token",
|
||||||
},
|
},
|
||||||
@ -326,7 +326,7 @@ func TestCommands_UpdateSession(t *testing.T) {
|
|||||||
expectFilter(
|
expectFilter(
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
session.NewAddedEvent(context.Background(),
|
session.NewAddedEvent(context.Background(),
|
||||||
&session.NewAggregate("sessionID", "org1").Aggregate,
|
&session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
&domain.UserAgent{
|
&domain.UserAgent{
|
||||||
FingerprintID: gu.Ptr("fp1"),
|
FingerprintID: gu.Ptr("fp1"),
|
||||||
IP: net.ParseIP("1.2.3.4"),
|
IP: net.ParseIP("1.2.3.4"),
|
||||||
@ -335,13 +335,11 @@ func TestCommands_UpdateSession(t *testing.T) {
|
|||||||
},
|
},
|
||||||
)),
|
)),
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
"tokenID")),
|
"tokenID")),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
tokenVerifier: func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error) {
|
tokenVerifier: newMockTokenVerifierInvalid(),
|
||||||
return caos_errs.ThrowPermissionDenied(nil, "COMMAND-sGr42", "Errors.Session.Token.Invalid")
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
args{
|
args{
|
||||||
ctx: context.Background(),
|
ctx: context.Background(),
|
||||||
@ -359,7 +357,7 @@ func TestCommands_UpdateSession(t *testing.T) {
|
|||||||
expectFilter(
|
expectFilter(
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
session.NewAddedEvent(context.Background(),
|
session.NewAddedEvent(context.Background(),
|
||||||
&session.NewAggregate("sessionID", "org1").Aggregate,
|
&session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
&domain.UserAgent{
|
&domain.UserAgent{
|
||||||
FingerprintID: gu.Ptr("fp1"),
|
FingerprintID: gu.Ptr("fp1"),
|
||||||
IP: net.ParseIP("1.2.3.4"),
|
IP: net.ParseIP("1.2.3.4"),
|
||||||
@ -368,7 +366,7 @@ func TestCommands_UpdateSession(t *testing.T) {
|
|||||||
},
|
},
|
||||||
)),
|
)),
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
"tokenID")),
|
"tokenID")),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -384,7 +382,7 @@ func TestCommands_UpdateSession(t *testing.T) {
|
|||||||
res{
|
res{
|
||||||
want: &SessionChanged{
|
want: &SessionChanged{
|
||||||
ObjectDetails: &domain.ObjectDetails{
|
ObjectDetails: &domain.ObjectDetails{
|
||||||
ResourceOwner: "org1",
|
ResourceOwner: "instance1",
|
||||||
},
|
},
|
||||||
ID: "sessionID",
|
ID: "sessionID",
|
||||||
NewToken: "",
|
NewToken: "",
|
||||||
@ -463,7 +461,7 @@ func TestCommands_updateSession(t *testing.T) {
|
|||||||
args{
|
args{
|
||||||
ctx: context.Background(),
|
ctx: context.Background(),
|
||||||
checks: &SessionCommands{
|
checks: &SessionCommands{
|
||||||
sessionWriteModel: NewSessionWriteModel("sessionID", "org1"),
|
sessionWriteModel: NewSessionWriteModel("sessionID", "instance1"),
|
||||||
sessionCommands: []SessionCommand{
|
sessionCommands: []SessionCommand{
|
||||||
func(ctx context.Context, cmd *SessionCommands) error {
|
func(ctx context.Context, cmd *SessionCommands) error {
|
||||||
return caos_errs.ThrowInternal(nil, "id", "check failed")
|
return caos_errs.ThrowInternal(nil, "id", "check failed")
|
||||||
@ -481,16 +479,16 @@ func TestCommands_updateSession(t *testing.T) {
|
|||||||
eventstore: eventstoreExpect(t),
|
eventstore: eventstoreExpect(t),
|
||||||
},
|
},
|
||||||
args{
|
args{
|
||||||
ctx: context.Background(),
|
ctx: authz.NewMockContext("instance1", "", ""),
|
||||||
checks: &SessionCommands{
|
checks: &SessionCommands{
|
||||||
sessionWriteModel: NewSessionWriteModel("sessionID", "org1"),
|
sessionWriteModel: NewSessionWriteModel("sessionID", "instance1"),
|
||||||
sessionCommands: []SessionCommand{},
|
sessionCommands: []SessionCommand{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
res{
|
res{
|
||||||
want: &SessionChanged{
|
want: &SessionChanged{
|
||||||
ObjectDetails: &domain.ObjectDetails{
|
ObjectDetails: &domain.ObjectDetails{
|
||||||
ResourceOwner: "org1",
|
ResourceOwner: "instance1",
|
||||||
},
|
},
|
||||||
ID: "sessionID",
|
ID: "sessionID",
|
||||||
NewToken: "",
|
NewToken: "",
|
||||||
@ -503,9 +501,9 @@ func TestCommands_updateSession(t *testing.T) {
|
|||||||
eventstore: eventstoreExpect(t),
|
eventstore: eventstoreExpect(t),
|
||||||
},
|
},
|
||||||
args{
|
args{
|
||||||
ctx: context.Background(),
|
ctx: authz.NewMockContext("instance1", "", ""),
|
||||||
checks: &SessionCommands{
|
checks: &SessionCommands{
|
||||||
sessionWriteModel: NewSessionWriteModel("sessionID", "org1"),
|
sessionWriteModel: NewSessionWriteModel("sessionID", "instance1"),
|
||||||
sessionCommands: []SessionCommand{},
|
sessionCommands: []SessionCommand{},
|
||||||
eventstore: eventstoreExpect(t),
|
eventstore: eventstoreExpect(t),
|
||||||
createToken: func(sessionID string) (string, string, error) {
|
createToken: func(sessionID string) (string, string, error) {
|
||||||
@ -528,19 +526,19 @@ func TestCommands_updateSession(t *testing.T) {
|
|||||||
fields{
|
fields{
|
||||||
eventstore: eventstoreExpect(t,
|
eventstore: eventstoreExpect(t,
|
||||||
expectPush(
|
expectPush(
|
||||||
session.NewLifetimeSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
session.NewLifetimeSetEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
10*time.Minute,
|
10*time.Minute,
|
||||||
),
|
),
|
||||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
"tokenID",
|
"tokenID",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
args{
|
args{
|
||||||
ctx: context.Background(),
|
ctx: authz.NewMockContext("instance1", "", ""),
|
||||||
checks: &SessionCommands{
|
checks: &SessionCommands{
|
||||||
sessionWriteModel: NewSessionWriteModel("sessionID", "org1"),
|
sessionWriteModel: NewSessionWriteModel("sessionID", "instance1"),
|
||||||
sessionCommands: []SessionCommand{},
|
sessionCommands: []SessionCommand{},
|
||||||
eventstore: eventstoreExpect(t),
|
eventstore: eventstoreExpect(t),
|
||||||
createToken: func(sessionID string) (string, string, error) {
|
createToken: func(sessionID string) (string, string, error) {
|
||||||
@ -557,7 +555,7 @@ func TestCommands_updateSession(t *testing.T) {
|
|||||||
res{
|
res{
|
||||||
want: &SessionChanged{
|
want: &SessionChanged{
|
||||||
ObjectDetails: &domain.ObjectDetails{
|
ObjectDetails: &domain.ObjectDetails{
|
||||||
ResourceOwner: "org1",
|
ResourceOwner: "instance1",
|
||||||
},
|
},
|
||||||
ID: "sessionID",
|
ID: "sessionID",
|
||||||
NewToken: "token",
|
NewToken: "token",
|
||||||
@ -569,27 +567,27 @@ func TestCommands_updateSession(t *testing.T) {
|
|||||||
fields{
|
fields{
|
||||||
eventstore: eventstoreExpect(t,
|
eventstore: eventstoreExpect(t,
|
||||||
expectPush(
|
expectPush(
|
||||||
session.NewUserCheckedEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
session.NewUserCheckedEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
"userID", testNow,
|
"userID", "org1", testNow,
|
||||||
),
|
),
|
||||||
session.NewPasswordCheckedEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
session.NewPasswordCheckedEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
testNow,
|
testNow,
|
||||||
),
|
),
|
||||||
session.NewMetadataSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
session.NewMetadataSetEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
map[string][]byte{"key": []byte("value")},
|
map[string][]byte{"key": []byte("value")},
|
||||||
),
|
),
|
||||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
"tokenID",
|
"tokenID",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
args{
|
args{
|
||||||
ctx: context.Background(),
|
ctx: authz.NewMockContext("instance1", "", ""),
|
||||||
checks: &SessionCommands{
|
checks: &SessionCommands{
|
||||||
sessionWriteModel: NewSessionWriteModel("sessionID", "org1"),
|
sessionWriteModel: NewSessionWriteModel("sessionID", "instance1"),
|
||||||
sessionCommands: []SessionCommand{
|
sessionCommands: []SessionCommand{
|
||||||
CheckUser("userID"),
|
CheckUser("userID", "org1"),
|
||||||
CheckPassword("password"),
|
CheckPassword("password"),
|
||||||
},
|
},
|
||||||
eventstore: eventstoreExpect(t,
|
eventstore: eventstoreExpect(t,
|
||||||
@ -621,7 +619,7 @@ func TestCommands_updateSession(t *testing.T) {
|
|||||||
res{
|
res{
|
||||||
want: &SessionChanged{
|
want: &SessionChanged{
|
||||||
ObjectDetails: &domain.ObjectDetails{
|
ObjectDetails: &domain.ObjectDetails{
|
||||||
ResourceOwner: "org1",
|
ResourceOwner: "instance1",
|
||||||
},
|
},
|
||||||
ID: "sessionID",
|
ID: "sessionID",
|
||||||
NewToken: "token",
|
NewToken: "token",
|
||||||
@ -634,11 +632,11 @@ func TestCommands_updateSession(t *testing.T) {
|
|||||||
eventstore: eventstoreExpect(t),
|
eventstore: eventstoreExpect(t),
|
||||||
},
|
},
|
||||||
args{
|
args{
|
||||||
ctx: context.Background(),
|
ctx: authz.NewMockContext("instance1", "", ""),
|
||||||
checks: &SessionCommands{
|
checks: &SessionCommands{
|
||||||
sessionWriteModel: NewSessionWriteModel("sessionID", "org1"),
|
sessionWriteModel: NewSessionWriteModel("sessionID", "instance1"),
|
||||||
sessionCommands: []SessionCommand{
|
sessionCommands: []SessionCommand{
|
||||||
CheckUser("userID"),
|
CheckUser("userID", "org1"),
|
||||||
CheckIntent("intent", "aW50ZW50"),
|
CheckIntent("intent", "aW50ZW50"),
|
||||||
},
|
},
|
||||||
eventstore: eventstoreExpect(t,
|
eventstore: eventstoreExpect(t,
|
||||||
@ -673,11 +671,11 @@ func TestCommands_updateSession(t *testing.T) {
|
|||||||
eventstore: eventstoreExpect(t),
|
eventstore: eventstoreExpect(t),
|
||||||
},
|
},
|
||||||
args{
|
args{
|
||||||
ctx: context.Background(),
|
ctx: authz.NewMockContext("instance1", "", ""),
|
||||||
checks: &SessionCommands{
|
checks: &SessionCommands{
|
||||||
sessionWriteModel: NewSessionWriteModel("sessionID", "org1"),
|
sessionWriteModel: NewSessionWriteModel("sessionID", "instance1"),
|
||||||
sessionCommands: []SessionCommand{
|
sessionCommands: []SessionCommand{
|
||||||
CheckUser("userID"),
|
CheckUser("userID", "org1"),
|
||||||
CheckIntent("intent", "aW50ZW50"),
|
CheckIntent("intent", "aW50ZW50"),
|
||||||
},
|
},
|
||||||
eventstore: eventstoreExpect(t,
|
eventstore: eventstoreExpect(t,
|
||||||
@ -722,11 +720,11 @@ func TestCommands_updateSession(t *testing.T) {
|
|||||||
eventstore: eventstoreExpect(t),
|
eventstore: eventstoreExpect(t),
|
||||||
},
|
},
|
||||||
args{
|
args{
|
||||||
ctx: context.Background(),
|
ctx: authz.NewMockContext("instance1", "", ""),
|
||||||
checks: &SessionCommands{
|
checks: &SessionCommands{
|
||||||
sessionWriteModel: NewSessionWriteModel("sessionID", "org1"),
|
sessionWriteModel: NewSessionWriteModel("sessionID", "instance1"),
|
||||||
sessionCommands: []SessionCommand{
|
sessionCommands: []SessionCommand{
|
||||||
CheckUser("userID"),
|
CheckUser("userID", "org1"),
|
||||||
CheckIntent("intent2", "aW50ZW50"),
|
CheckIntent("intent2", "aW50ZW50"),
|
||||||
},
|
},
|
||||||
eventstore: eventstoreExpect(t),
|
eventstore: eventstoreExpect(t),
|
||||||
@ -753,23 +751,23 @@ func TestCommands_updateSession(t *testing.T) {
|
|||||||
fields{
|
fields{
|
||||||
eventstore: eventstoreExpect(t,
|
eventstore: eventstoreExpect(t,
|
||||||
expectPush(
|
expectPush(
|
||||||
session.NewUserCheckedEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
session.NewUserCheckedEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
"userID", testNow),
|
"userID", "org1", testNow),
|
||||||
session.NewIntentCheckedEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
session.NewIntentCheckedEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
testNow),
|
testNow),
|
||||||
session.NewMetadataSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
session.NewMetadataSetEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
map[string][]byte{"key": []byte("value")}),
|
map[string][]byte{"key": []byte("value")}),
|
||||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
"tokenID"),
|
"tokenID"),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
args{
|
args{
|
||||||
ctx: context.Background(),
|
ctx: authz.NewMockContext("instance1", "", ""),
|
||||||
checks: &SessionCommands{
|
checks: &SessionCommands{
|
||||||
sessionWriteModel: NewSessionWriteModel("sessionID", "org1"),
|
sessionWriteModel: NewSessionWriteModel("sessionID", "instance1"),
|
||||||
sessionCommands: []SessionCommand{
|
sessionCommands: []SessionCommand{
|
||||||
CheckUser("userID"),
|
CheckUser("userID", "org1"),
|
||||||
CheckIntent("intent", "aW50ZW50"),
|
CheckIntent("intent", "aW50ZW50"),
|
||||||
},
|
},
|
||||||
eventstore: eventstoreExpect(t,
|
eventstore: eventstoreExpect(t,
|
||||||
@ -807,7 +805,7 @@ func TestCommands_updateSession(t *testing.T) {
|
|||||||
res{
|
res{
|
||||||
want: &SessionChanged{
|
want: &SessionChanged{
|
||||||
ObjectDetails: &domain.ObjectDetails{
|
ObjectDetails: &domain.ObjectDetails{
|
||||||
ResourceOwner: "org1",
|
ResourceOwner: "instance1",
|
||||||
},
|
},
|
||||||
ID: "sessionID",
|
ID: "sessionID",
|
||||||
NewToken: "token",
|
NewToken: "token",
|
||||||
@ -828,13 +826,13 @@ func TestCommands_updateSession(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCheckTOTP(t *testing.T) {
|
func TestCheckTOTP(t *testing.T) {
|
||||||
ctx := authz.NewMockContext("", "org1", "user1")
|
ctx := authz.NewMockContext("instance1", "org1", "user1")
|
||||||
|
|
||||||
cryptoAlg := crypto.CreateMockEncryptionAlg(gomock.NewController(t))
|
cryptoAlg := crypto.CreateMockEncryptionAlg(gomock.NewController(t))
|
||||||
key, secret, err := domain.NewTOTPKey("example.com", "user1", cryptoAlg)
|
key, secret, err := domain.NewTOTPKey("example.com", "user1", cryptoAlg)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
sessAgg := &session.NewAggregate("session1", "org1").Aggregate
|
sessAgg := &session.NewAggregate("session1", "instance1").Aggregate
|
||||||
userAgg := &user.NewAggregate("user1", "org1").Aggregate
|
userAgg := &user.NewAggregate("user1", "org1").Aggregate
|
||||||
|
|
||||||
code, err := totp.GenerateCode(key.Secret(), testNow)
|
code, err := totp.GenerateCode(key.Secret(), testNow)
|
||||||
@ -961,8 +959,9 @@ func TestCheckTOTP(t *testing.T) {
|
|||||||
|
|
||||||
func TestCommands_TerminateSession(t *testing.T) {
|
func TestCommands_TerminateSession(t *testing.T) {
|
||||||
type fields struct {
|
type fields struct {
|
||||||
eventstore *eventstore.Eventstore
|
eventstore func(t *testing.T) *eventstore.Eventstore
|
||||||
tokenVerifier func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error)
|
tokenVerifier func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error)
|
||||||
|
checkPermission domain.PermissionCheck
|
||||||
}
|
}
|
||||||
type args struct {
|
type args struct {
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
@ -982,7 +981,7 @@ func TestCommands_TerminateSession(t *testing.T) {
|
|||||||
{
|
{
|
||||||
"eventstore failed",
|
"eventstore failed",
|
||||||
fields{
|
fields{
|
||||||
eventstore: eventstoreExpect(t,
|
eventstore: expectEventstore(
|
||||||
expectFilterError(caos_errs.ThrowInternal(nil, "id", "filter failed")),
|
expectFilterError(caos_errs.ThrowInternal(nil, "id", "filter failed")),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
@ -996,11 +995,11 @@ func TestCommands_TerminateSession(t *testing.T) {
|
|||||||
{
|
{
|
||||||
"invalid session token",
|
"invalid session token",
|
||||||
fields{
|
fields{
|
||||||
eventstore: eventstoreExpect(t,
|
eventstore: expectEventstore(
|
||||||
expectFilter(
|
expectFilter(
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
session.NewAddedEvent(context.Background(),
|
session.NewAddedEvent(context.Background(),
|
||||||
&session.NewAggregate("sessionID", "org1").Aggregate,
|
&session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
&domain.UserAgent{
|
&domain.UserAgent{
|
||||||
FingerprintID: gu.Ptr("fp1"),
|
FingerprintID: gu.Ptr("fp1"),
|
||||||
IP: net.ParseIP("1.2.3.4"),
|
IP: net.ParseIP("1.2.3.4"),
|
||||||
@ -1009,13 +1008,11 @@ func TestCommands_TerminateSession(t *testing.T) {
|
|||||||
},
|
},
|
||||||
)),
|
)),
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
"tokenID")),
|
"tokenID")),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
tokenVerifier: func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error) {
|
tokenVerifier: newMockTokenVerifierInvalid(),
|
||||||
return caos_errs.ThrowPermissionDenied(nil, "COMMAND-sGr42", "Errors.Session.Token.Invalid")
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
args{
|
args{
|
||||||
ctx: context.Background(),
|
ctx: context.Background(),
|
||||||
@ -1027,13 +1024,13 @@ func TestCommands_TerminateSession(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"not active",
|
"missing permission",
|
||||||
fields{
|
fields{
|
||||||
eventstore: eventstoreExpect(t,
|
eventstore: expectEventstore(
|
||||||
expectFilter(
|
expectFilter(
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
session.NewAddedEvent(context.Background(),
|
session.NewAddedEvent(context.Background(),
|
||||||
&session.NewAggregate("sessionID", "org1").Aggregate,
|
&session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
&domain.UserAgent{
|
&domain.UserAgent{
|
||||||
FingerprintID: gu.Ptr("fp1"),
|
FingerprintID: gu.Ptr("fp1"),
|
||||||
IP: net.ParseIP("1.2.3.4"),
|
IP: net.ParseIP("1.2.3.4"),
|
||||||
@ -1042,10 +1039,41 @@ func TestCommands_TerminateSession(t *testing.T) {
|
|||||||
},
|
},
|
||||||
)),
|
)),
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
|
"tokenID")),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
checkPermission: newMockPermissionCheckNotAllowed(),
|
||||||
|
},
|
||||||
|
args{
|
||||||
|
ctx: context.Background(),
|
||||||
|
sessionID: "sessionID",
|
||||||
|
sessionToken: "",
|
||||||
|
},
|
||||||
|
res{
|
||||||
|
err: caos_errs.ThrowPermissionDenied(nil, "AUTHZ-HKJD33", "Errors.PermissionDenied"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"not active",
|
||||||
|
fields{
|
||||||
|
eventstore: expectEventstore(
|
||||||
|
expectFilter(
|
||||||
|
eventFromEventPusher(
|
||||||
|
session.NewAddedEvent(context.Background(),
|
||||||
|
&session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
|
&domain.UserAgent{
|
||||||
|
FingerprintID: gu.Ptr("fp1"),
|
||||||
|
IP: net.ParseIP("1.2.3.4"),
|
||||||
|
Description: gu.Ptr("firefox"),
|
||||||
|
Header: http.Header{"foo": []string{"bar"}},
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
eventFromEventPusher(
|
||||||
|
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
"tokenID")),
|
"tokenID")),
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
session.NewTerminateEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate)),
|
session.NewTerminateEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
tokenVerifier: func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error) {
|
tokenVerifier: func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error) {
|
||||||
@ -1059,18 +1087,18 @@ func TestCommands_TerminateSession(t *testing.T) {
|
|||||||
},
|
},
|
||||||
res{
|
res{
|
||||||
want: &domain.ObjectDetails{
|
want: &domain.ObjectDetails{
|
||||||
ResourceOwner: "org1",
|
ResourceOwner: "instance1",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"push failed",
|
"push failed",
|
||||||
fields{
|
fields{
|
||||||
eventstore: eventstoreExpect(t,
|
eventstore: expectEventstore(
|
||||||
expectFilter(
|
expectFilter(
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
session.NewAddedEvent(context.Background(),
|
session.NewAddedEvent(context.Background(),
|
||||||
&session.NewAggregate("sessionID", "org1").Aggregate,
|
&session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
&domain.UserAgent{
|
&domain.UserAgent{
|
||||||
FingerprintID: gu.Ptr("fp1"),
|
FingerprintID: gu.Ptr("fp1"),
|
||||||
IP: net.ParseIP("1.2.3.4"),
|
IP: net.ParseIP("1.2.3.4"),
|
||||||
@ -1079,13 +1107,13 @@ func TestCommands_TerminateSession(t *testing.T) {
|
|||||||
},
|
},
|
||||||
)),
|
)),
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
"tokenID"),
|
"tokenID"),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
expectPushFailed(
|
expectPushFailed(
|
||||||
caos_errs.ThrowInternal(nil, "id", "pushed failed"),
|
caos_errs.ThrowInternal(nil, "id", "pushed failed"),
|
||||||
session.NewTerminateEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate),
|
session.NewTerminateEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
tokenVerifier: func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error) {
|
tokenVerifier: func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error) {
|
||||||
@ -1102,13 +1130,13 @@ func TestCommands_TerminateSession(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"terminate",
|
"terminate with token",
|
||||||
fields{
|
fields{
|
||||||
eventstore: eventstoreExpect(t,
|
eventstore: expectEventstore(
|
||||||
expectFilter(
|
expectFilter(
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
session.NewAddedEvent(context.Background(),
|
session.NewAddedEvent(context.Background(),
|
||||||
&session.NewAggregate("sessionID", "org1").Aggregate,
|
&session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
&domain.UserAgent{
|
&domain.UserAgent{
|
||||||
FingerprintID: gu.Ptr("fp1"),
|
FingerprintID: gu.Ptr("fp1"),
|
||||||
IP: net.ParseIP("1.2.3.4"),
|
IP: net.ParseIP("1.2.3.4"),
|
||||||
@ -1117,12 +1145,12 @@ func TestCommands_TerminateSession(t *testing.T) {
|
|||||||
},
|
},
|
||||||
)),
|
)),
|
||||||
eventFromEventPusher(
|
eventFromEventPusher(
|
||||||
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate,
|
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
"tokenID"),
|
"tokenID"),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
expectPush(
|
expectPush(
|
||||||
session.NewTerminateEvent(context.Background(), &session.NewAggregate("sessionID", "org1").Aggregate),
|
session.NewTerminateEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
tokenVerifier: func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error) {
|
tokenVerifier: func(ctx context.Context, sessionToken, sessionID, tokenID string) (err error) {
|
||||||
@ -1136,7 +1164,90 @@ func TestCommands_TerminateSession(t *testing.T) {
|
|||||||
},
|
},
|
||||||
res{
|
res{
|
||||||
want: &domain.ObjectDetails{
|
want: &domain.ObjectDetails{
|
||||||
ResourceOwner: "org1",
|
ResourceOwner: "instance1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"terminate own session",
|
||||||
|
fields{
|
||||||
|
eventstore: expectEventstore(
|
||||||
|
expectFilter(
|
||||||
|
eventFromEventPusher(
|
||||||
|
session.NewAddedEvent(context.Background(),
|
||||||
|
&session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
|
&domain.UserAgent{
|
||||||
|
FingerprintID: gu.Ptr("fp1"),
|
||||||
|
IP: net.ParseIP("1.2.3.4"),
|
||||||
|
Description: gu.Ptr("firefox"),
|
||||||
|
Header: http.Header{"foo": []string{"bar"}},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
session.NewUserCheckedEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
|
"user1", "org1", testNow),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
|
"tokenID"),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
expectPush(
|
||||||
|
session.NewTerminateEvent(authz.NewMockContext("instance1", "org1", "user1"), &session.NewAggregate("sessionID", "instance1").Aggregate),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
args{
|
||||||
|
ctx: authz.NewMockContext("instance1", "org1", "user1"),
|
||||||
|
sessionID: "sessionID",
|
||||||
|
sessionToken: "",
|
||||||
|
},
|
||||||
|
res{
|
||||||
|
want: &domain.ObjectDetails{
|
||||||
|
ResourceOwner: "instance1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"terminate with permission",
|
||||||
|
fields{
|
||||||
|
eventstore: expectEventstore(
|
||||||
|
expectFilter(
|
||||||
|
eventFromEventPusher(
|
||||||
|
session.NewAddedEvent(context.Background(),
|
||||||
|
&session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
|
&domain.UserAgent{
|
||||||
|
FingerprintID: gu.Ptr("fp1"),
|
||||||
|
IP: net.ParseIP("1.2.3.4"),
|
||||||
|
Description: gu.Ptr("firefox"),
|
||||||
|
Header: http.Header{"foo": []string{"bar"}},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
session.NewUserCheckedEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
|
"userID", "org1", testNow),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "instance1").Aggregate,
|
||||||
|
"tokenID"),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
expectPush(
|
||||||
|
session.NewTerminateEvent(authz.NewMockContext("instance1", "org1", "admin1"), &session.NewAggregate("sessionID", "instance1").Aggregate),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
checkPermission: newMockPermissionCheckAllowed(),
|
||||||
|
},
|
||||||
|
args{
|
||||||
|
ctx: authz.NewMockContext("instance1", "org1", "admin1"),
|
||||||
|
sessionID: "sessionID",
|
||||||
|
sessionToken: "",
|
||||||
|
},
|
||||||
|
res{
|
||||||
|
want: &domain.ObjectDetails{
|
||||||
|
ResourceOwner: "instance1",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1144,8 +1255,9 @@ func TestCommands_TerminateSession(t *testing.T) {
|
|||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
c := &Commands{
|
c := &Commands{
|
||||||
eventstore: tt.fields.eventstore,
|
eventstore: tt.fields.eventstore(t),
|
||||||
sessionTokenVerifier: tt.fields.tokenVerifier,
|
sessionTokenVerifier: tt.fields.tokenVerifier,
|
||||||
|
checkPermission: tt.fields.checkPermission,
|
||||||
}
|
}
|
||||||
got, err := c.TerminateSession(tt.args.ctx, tt.args.sessionID, tt.args.sessionToken)
|
got, err := c.TerminateSession(tt.args.ctx, tt.args.sessionID, tt.args.sessionToken)
|
||||||
require.ErrorIs(t, err, tt.res.err)
|
require.ErrorIs(t, err, tt.res.err)
|
||||||
|
@ -29,9 +29,9 @@ func (s *SessionCommands) getHumanWebAuthNTokens(ctx context.Context, userVerifi
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *SessionCommands) getHumanWebAuthNTokenReadModel(ctx context.Context, userVerification domain.UserVerificationRequirement) (readModel HumanWebAuthNTokensReadModel, err error) {
|
func (s *SessionCommands) getHumanWebAuthNTokenReadModel(ctx context.Context, userVerification domain.UserVerificationRequirement) (readModel HumanWebAuthNTokensReadModel, err error) {
|
||||||
readModel = NewHumanU2FTokensReadModel(s.sessionWriteModel.UserID, "")
|
readModel = NewHumanU2FTokensReadModel(s.sessionWriteModel.UserID, s.sessionWriteModel.UserResourceOwner)
|
||||||
if userVerification == domain.UserVerificationRequirementRequired {
|
if userVerification == domain.UserVerificationRequirementRequired {
|
||||||
readModel = NewHumanPasswordlessTokensReadModel(s.sessionWriteModel.UserID, "")
|
readModel = NewHumanPasswordlessTokensReadModel(s.sessionWriteModel.UserID, s.sessionWriteModel.UserResourceOwner)
|
||||||
}
|
}
|
||||||
err = s.eventstore.FilterToQueryReducer(ctx, readModel)
|
err = s.eventstore.FilterToQueryReducer(ctx, readModel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -14,7 +14,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
SessionsProjectionTable = "projections.sessions7"
|
SessionsProjectionTable = "projections.sessions8"
|
||||||
|
|
||||||
SessionColumnID = "id"
|
SessionColumnID = "id"
|
||||||
SessionColumnCreationDate = "creation_date"
|
SessionColumnCreationDate = "creation_date"
|
||||||
@ -25,6 +25,7 @@ const (
|
|||||||
SessionColumnInstanceID = "instance_id"
|
SessionColumnInstanceID = "instance_id"
|
||||||
SessionColumnCreator = "creator"
|
SessionColumnCreator = "creator"
|
||||||
SessionColumnUserID = "user_id"
|
SessionColumnUserID = "user_id"
|
||||||
|
SessionColumnUserResourceOwner = "user_resource_owner"
|
||||||
SessionColumnUserCheckedAt = "user_checked_at"
|
SessionColumnUserCheckedAt = "user_checked_at"
|
||||||
SessionColumnPasswordCheckedAt = "password_checked_at"
|
SessionColumnPasswordCheckedAt = "password_checked_at"
|
||||||
SessionColumnIntentCheckedAt = "intent_checked_at"
|
SessionColumnIntentCheckedAt = "intent_checked_at"
|
||||||
@ -64,6 +65,7 @@ func (*sessionProjection) Init() *old_handler.Check {
|
|||||||
handler.NewColumn(SessionColumnInstanceID, handler.ColumnTypeText),
|
handler.NewColumn(SessionColumnInstanceID, handler.ColumnTypeText),
|
||||||
handler.NewColumn(SessionColumnCreator, handler.ColumnTypeText),
|
handler.NewColumn(SessionColumnCreator, handler.ColumnTypeText),
|
||||||
handler.NewColumn(SessionColumnUserID, handler.ColumnTypeText, handler.Nullable()),
|
handler.NewColumn(SessionColumnUserID, handler.ColumnTypeText, handler.Nullable()),
|
||||||
|
handler.NewColumn(SessionColumnUserResourceOwner, handler.ColumnTypeText, handler.Nullable()),
|
||||||
handler.NewColumn(SessionColumnUserCheckedAt, handler.ColumnTypeTimestamp, handler.Nullable()),
|
handler.NewColumn(SessionColumnUserCheckedAt, handler.ColumnTypeTimestamp, handler.Nullable()),
|
||||||
handler.NewColumn(SessionColumnPasswordCheckedAt, handler.ColumnTypeTimestamp, handler.Nullable()),
|
handler.NewColumn(SessionColumnPasswordCheckedAt, handler.ColumnTypeTimestamp, handler.Nullable()),
|
||||||
handler.NewColumn(SessionColumnIntentCheckedAt, handler.ColumnTypeTimestamp, handler.Nullable()),
|
handler.NewColumn(SessionColumnIntentCheckedAt, handler.ColumnTypeTimestamp, handler.Nullable()),
|
||||||
@ -213,6 +215,7 @@ func (p *sessionProjection) reduceUserChecked(event eventstore.Event) (*handler.
|
|||||||
handler.NewCol(SessionColumnChangeDate, e.CreationDate()),
|
handler.NewCol(SessionColumnChangeDate, e.CreationDate()),
|
||||||
handler.NewCol(SessionColumnSequence, e.Sequence()),
|
handler.NewCol(SessionColumnSequence, e.Sequence()),
|
||||||
handler.NewCol(SessionColumnUserID, e.UserID),
|
handler.NewCol(SessionColumnUserID, e.UserID),
|
||||||
|
handler.NewCol(SessionColumnUserResourceOwner, e.UserResourceOwner),
|
||||||
handler.NewCol(SessionColumnUserCheckedAt, e.CheckedAt),
|
handler.NewCol(SessionColumnUserCheckedAt, e.CheckedAt),
|
||||||
},
|
},
|
||||||
[]handler.Condition{
|
[]handler.Condition{
|
||||||
@ -430,6 +433,7 @@ func (p *sessionProjection) reducePasswordChanged(event eventstore.Event) (*hand
|
|||||||
},
|
},
|
||||||
[]handler.Condition{
|
[]handler.Condition{
|
||||||
handler.NewCond(SessionColumnUserID, e.Aggregate().ID),
|
handler.NewCond(SessionColumnUserID, e.Aggregate().ID),
|
||||||
|
handler.NewCond(SessionColumnInstanceID, e.Aggregate().InstanceID),
|
||||||
handler.NewLessThanCond(SessionColumnPasswordCheckedAt, e.CreationDate()),
|
handler.NewLessThanCond(SessionColumnPasswordCheckedAt, e.CreationDate()),
|
||||||
},
|
},
|
||||||
), nil
|
), nil
|
||||||
|
@ -51,7 +51,7 @@ func TestSessionProjection_reduces(t *testing.T) {
|
|||||||
executer: &testExecuter{
|
executer: &testExecuter{
|
||||||
executions: []execution{
|
executions: []execution{
|
||||||
{
|
{
|
||||||
expectedStmt: "INSERT INTO projections.sessions7 (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)",
|
expectedStmt: "INSERT INTO projections.sessions8 (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)",
|
||||||
expectedArgs: []interface{}{
|
expectedArgs: []interface{}{
|
||||||
"agg-id",
|
"agg-id",
|
||||||
"instance-id",
|
"instance-id",
|
||||||
@ -79,6 +79,7 @@ func TestSessionProjection_reduces(t *testing.T) {
|
|||||||
session.AggregateType,
|
session.AggregateType,
|
||||||
[]byte(`{
|
[]byte(`{
|
||||||
"userId": "user-id",
|
"userId": "user-id",
|
||||||
|
"userResourceOwner": "org-id",
|
||||||
"checkedAt": "2023-05-04T00:00:00Z"
|
"checkedAt": "2023-05-04T00:00:00Z"
|
||||||
}`),
|
}`),
|
||||||
), session.UserCheckedEventMapper),
|
), session.UserCheckedEventMapper),
|
||||||
@ -90,11 +91,12 @@ func TestSessionProjection_reduces(t *testing.T) {
|
|||||||
executer: &testExecuter{
|
executer: &testExecuter{
|
||||||
executions: []execution{
|
executions: []execution{
|
||||||
{
|
{
|
||||||
expectedStmt: "UPDATE projections.sessions7 SET (change_date, sequence, user_id, user_checked_at) = ($1, $2, $3, $4) WHERE (id = $5) AND (instance_id = $6)",
|
expectedStmt: "UPDATE projections.sessions8 SET (change_date, sequence, user_id, user_resource_owner, user_checked_at) = ($1, $2, $3, $4, $5) WHERE (id = $6) AND (instance_id = $7)",
|
||||||
expectedArgs: []interface{}{
|
expectedArgs: []interface{}{
|
||||||
anyArg{},
|
anyArg{},
|
||||||
anyArg{},
|
anyArg{},
|
||||||
"user-id",
|
"user-id",
|
||||||
|
"org-id",
|
||||||
time.Date(2023, time.May, 4, 0, 0, 0, 0, time.UTC),
|
time.Date(2023, time.May, 4, 0, 0, 0, 0, time.UTC),
|
||||||
"agg-id",
|
"agg-id",
|
||||||
"instance-id",
|
"instance-id",
|
||||||
@ -122,7 +124,7 @@ func TestSessionProjection_reduces(t *testing.T) {
|
|||||||
executer: &testExecuter{
|
executer: &testExecuter{
|
||||||
executions: []execution{
|
executions: []execution{
|
||||||
{
|
{
|
||||||
expectedStmt: "UPDATE projections.sessions7 SET (change_date, sequence, password_checked_at) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
expectedStmt: "UPDATE projections.sessions8 SET (change_date, sequence, password_checked_at) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||||
expectedArgs: []interface{}{
|
expectedArgs: []interface{}{
|
||||||
anyArg{},
|
anyArg{},
|
||||||
anyArg{},
|
anyArg{},
|
||||||
@ -154,7 +156,7 @@ func TestSessionProjection_reduces(t *testing.T) {
|
|||||||
executer: &testExecuter{
|
executer: &testExecuter{
|
||||||
executions: []execution{
|
executions: []execution{
|
||||||
{
|
{
|
||||||
expectedStmt: "UPDATE projections.sessions7 SET (change_date, sequence, webauthn_checked_at, webauthn_user_verified) = ($1, $2, $3, $4) WHERE (id = $5) AND (instance_id = $6)",
|
expectedStmt: "UPDATE projections.sessions8 SET (change_date, sequence, webauthn_checked_at, webauthn_user_verified) = ($1, $2, $3, $4) WHERE (id = $5) AND (instance_id = $6)",
|
||||||
expectedArgs: []interface{}{
|
expectedArgs: []interface{}{
|
||||||
anyArg{},
|
anyArg{},
|
||||||
anyArg{},
|
anyArg{},
|
||||||
@ -186,7 +188,7 @@ func TestSessionProjection_reduces(t *testing.T) {
|
|||||||
executer: &testExecuter{
|
executer: &testExecuter{
|
||||||
executions: []execution{
|
executions: []execution{
|
||||||
{
|
{
|
||||||
expectedStmt: "UPDATE projections.sessions7 SET (change_date, sequence, intent_checked_at) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
expectedStmt: "UPDATE projections.sessions8 SET (change_date, sequence, intent_checked_at) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||||
expectedArgs: []interface{}{
|
expectedArgs: []interface{}{
|
||||||
anyArg{},
|
anyArg{},
|
||||||
anyArg{},
|
anyArg{},
|
||||||
@ -217,7 +219,7 @@ func TestSessionProjection_reduces(t *testing.T) {
|
|||||||
executer: &testExecuter{
|
executer: &testExecuter{
|
||||||
executions: []execution{
|
executions: []execution{
|
||||||
{
|
{
|
||||||
expectedStmt: "UPDATE projections.sessions7 SET (change_date, sequence, totp_checked_at) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
expectedStmt: "UPDATE projections.sessions8 SET (change_date, sequence, totp_checked_at) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||||
expectedArgs: []interface{}{
|
expectedArgs: []interface{}{
|
||||||
anyArg{},
|
anyArg{},
|
||||||
anyArg{},
|
anyArg{},
|
||||||
@ -248,7 +250,7 @@ func TestSessionProjection_reduces(t *testing.T) {
|
|||||||
executer: &testExecuter{
|
executer: &testExecuter{
|
||||||
executions: []execution{
|
executions: []execution{
|
||||||
{
|
{
|
||||||
expectedStmt: "UPDATE projections.sessions7 SET (change_date, sequence, token_id) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
expectedStmt: "UPDATE projections.sessions8 SET (change_date, sequence, token_id) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||||
expectedArgs: []interface{}{
|
expectedArgs: []interface{}{
|
||||||
anyArg{},
|
anyArg{},
|
||||||
anyArg{},
|
anyArg{},
|
||||||
@ -281,7 +283,7 @@ func TestSessionProjection_reduces(t *testing.T) {
|
|||||||
executer: &testExecuter{
|
executer: &testExecuter{
|
||||||
executions: []execution{
|
executions: []execution{
|
||||||
{
|
{
|
||||||
expectedStmt: "UPDATE projections.sessions7 SET (change_date, sequence, metadata) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
expectedStmt: "UPDATE projections.sessions8 SET (change_date, sequence, metadata) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||||
expectedArgs: []interface{}{
|
expectedArgs: []interface{}{
|
||||||
anyArg{},
|
anyArg{},
|
||||||
anyArg{},
|
anyArg{},
|
||||||
@ -314,7 +316,7 @@ func TestSessionProjection_reduces(t *testing.T) {
|
|||||||
executer: &testExecuter{
|
executer: &testExecuter{
|
||||||
executions: []execution{
|
executions: []execution{
|
||||||
{
|
{
|
||||||
expectedStmt: "UPDATE projections.sessions7 SET (change_date, sequence, expiration) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
expectedStmt: "UPDATE projections.sessions8 SET (change_date, sequence, expiration) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||||
expectedArgs: []interface{}{
|
expectedArgs: []interface{}{
|
||||||
anyArg{},
|
anyArg{},
|
||||||
anyArg{},
|
anyArg{},
|
||||||
@ -343,7 +345,7 @@ func TestSessionProjection_reduces(t *testing.T) {
|
|||||||
executer: &testExecuter{
|
executer: &testExecuter{
|
||||||
executions: []execution{
|
executions: []execution{
|
||||||
{
|
{
|
||||||
expectedStmt: "DELETE FROM projections.sessions7 WHERE (id = $1) AND (instance_id = $2)",
|
expectedStmt: "DELETE FROM projections.sessions8 WHERE (id = $1) AND (instance_id = $2)",
|
||||||
expectedArgs: []interface{}{
|
expectedArgs: []interface{}{
|
||||||
"agg-id",
|
"agg-id",
|
||||||
"instance-id",
|
"instance-id",
|
||||||
@ -370,7 +372,7 @@ func TestSessionProjection_reduces(t *testing.T) {
|
|||||||
executer: &testExecuter{
|
executer: &testExecuter{
|
||||||
executions: []execution{
|
executions: []execution{
|
||||||
{
|
{
|
||||||
expectedStmt: "DELETE FROM projections.sessions7 WHERE (instance_id = $1)",
|
expectedStmt: "DELETE FROM projections.sessions8 WHERE (instance_id = $1)",
|
||||||
expectedArgs: []interface{}{
|
expectedArgs: []interface{}{
|
||||||
"agg-id",
|
"agg-id",
|
||||||
},
|
},
|
||||||
@ -400,10 +402,11 @@ func TestSessionProjection_reduces(t *testing.T) {
|
|||||||
executer: &testExecuter{
|
executer: &testExecuter{
|
||||||
executions: []execution{
|
executions: []execution{
|
||||||
{
|
{
|
||||||
expectedStmt: "UPDATE projections.sessions7 SET password_checked_at = $1 WHERE (user_id = $2) AND (password_checked_at < $3)",
|
expectedStmt: "UPDATE projections.sessions8 SET password_checked_at = $1 WHERE (user_id = $2) AND (instance_id = $3) AND (password_checked_at < $4)",
|
||||||
expectedArgs: []interface{}{
|
expectedArgs: []interface{}{
|
||||||
nil,
|
nil,
|
||||||
"agg-id",
|
"agg-id",
|
||||||
|
"instance-id",
|
||||||
anyArg{},
|
anyArg{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -130,6 +130,10 @@ var (
|
|||||||
name: projection.SessionColumnUserID,
|
name: projection.SessionColumnUserID,
|
||||||
table: sessionsTable,
|
table: sessionsTable,
|
||||||
}
|
}
|
||||||
|
SessionColumnUserResourceOwner = Column{
|
||||||
|
name: projection.SessionColumnUserResourceOwner,
|
||||||
|
table: sessionsTable,
|
||||||
|
}
|
||||||
SessionColumnUserCheckedAt = Column{
|
SessionColumnUserCheckedAt = Column{
|
||||||
name: projection.SessionColumnUserCheckedAt,
|
name: projection.SessionColumnUserCheckedAt,
|
||||||
table: sessionsTable,
|
table: sessionsTable,
|
||||||
@ -287,10 +291,10 @@ func prepareSessionQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuil
|
|||||||
SessionColumnResourceOwner.identifier(),
|
SessionColumnResourceOwner.identifier(),
|
||||||
SessionColumnCreator.identifier(),
|
SessionColumnCreator.identifier(),
|
||||||
SessionColumnUserID.identifier(),
|
SessionColumnUserID.identifier(),
|
||||||
|
SessionColumnUserResourceOwner.identifier(),
|
||||||
SessionColumnUserCheckedAt.identifier(),
|
SessionColumnUserCheckedAt.identifier(),
|
||||||
LoginNameNameCol.identifier(),
|
LoginNameNameCol.identifier(),
|
||||||
HumanDisplayNameCol.identifier(),
|
HumanDisplayNameCol.identifier(),
|
||||||
UserResourceOwnerCol.identifier(),
|
|
||||||
SessionColumnPasswordCheckedAt.identifier(),
|
SessionColumnPasswordCheckedAt.identifier(),
|
||||||
SessionColumnIntentCheckedAt.identifier(),
|
SessionColumnIntentCheckedAt.identifier(),
|
||||||
SessionColumnWebAuthNCheckedAt.identifier(),
|
SessionColumnWebAuthNCheckedAt.identifier(),
|
||||||
@ -314,10 +318,10 @@ func prepareSessionQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuil
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
userID sql.NullString
|
userID sql.NullString
|
||||||
|
userResourceOwner sql.NullString
|
||||||
userCheckedAt sql.NullTime
|
userCheckedAt sql.NullTime
|
||||||
loginName sql.NullString
|
loginName sql.NullString
|
||||||
displayName sql.NullString
|
displayName sql.NullString
|
||||||
userResourceOwner sql.NullString
|
|
||||||
passwordCheckedAt sql.NullTime
|
passwordCheckedAt sql.NullTime
|
||||||
intentCheckedAt sql.NullTime
|
intentCheckedAt sql.NullTime
|
||||||
webAuthNCheckedAt sql.NullTime
|
webAuthNCheckedAt sql.NullTime
|
||||||
@ -341,10 +345,10 @@ func prepareSessionQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuil
|
|||||||
&session.ResourceOwner,
|
&session.ResourceOwner,
|
||||||
&session.Creator,
|
&session.Creator,
|
||||||
&userID,
|
&userID,
|
||||||
|
&userResourceOwner,
|
||||||
&userCheckedAt,
|
&userCheckedAt,
|
||||||
&loginName,
|
&loginName,
|
||||||
&displayName,
|
&displayName,
|
||||||
&userResourceOwner,
|
|
||||||
&passwordCheckedAt,
|
&passwordCheckedAt,
|
||||||
&intentCheckedAt,
|
&intentCheckedAt,
|
||||||
&webAuthNCheckedAt,
|
&webAuthNCheckedAt,
|
||||||
@ -369,10 +373,10 @@ func prepareSessionQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuil
|
|||||||
}
|
}
|
||||||
|
|
||||||
session.UserFactor.UserID = userID.String
|
session.UserFactor.UserID = userID.String
|
||||||
|
session.UserFactor.ResourceOwner = userResourceOwner.String
|
||||||
session.UserFactor.UserCheckedAt = userCheckedAt.Time
|
session.UserFactor.UserCheckedAt = userCheckedAt.Time
|
||||||
session.UserFactor.LoginName = loginName.String
|
session.UserFactor.LoginName = loginName.String
|
||||||
session.UserFactor.DisplayName = displayName.String
|
session.UserFactor.DisplayName = displayName.String
|
||||||
session.UserFactor.ResourceOwner = userResourceOwner.String
|
|
||||||
session.PasswordFactor.PasswordCheckedAt = passwordCheckedAt.Time
|
session.PasswordFactor.PasswordCheckedAt = passwordCheckedAt.Time
|
||||||
session.IntentFactor.IntentCheckedAt = intentCheckedAt.Time
|
session.IntentFactor.IntentCheckedAt = intentCheckedAt.Time
|
||||||
session.WebAuthNFactor.WebAuthNCheckedAt = webAuthNCheckedAt.Time
|
session.WebAuthNFactor.WebAuthNCheckedAt = webAuthNCheckedAt.Time
|
||||||
@ -400,10 +404,10 @@ func prepareSessionsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBui
|
|||||||
SessionColumnResourceOwner.identifier(),
|
SessionColumnResourceOwner.identifier(),
|
||||||
SessionColumnCreator.identifier(),
|
SessionColumnCreator.identifier(),
|
||||||
SessionColumnUserID.identifier(),
|
SessionColumnUserID.identifier(),
|
||||||
|
SessionColumnUserResourceOwner.identifier(),
|
||||||
SessionColumnUserCheckedAt.identifier(),
|
SessionColumnUserCheckedAt.identifier(),
|
||||||
LoginNameNameCol.identifier(),
|
LoginNameNameCol.identifier(),
|
||||||
HumanDisplayNameCol.identifier(),
|
HumanDisplayNameCol.identifier(),
|
||||||
UserResourceOwnerCol.identifier(),
|
|
||||||
SessionColumnPasswordCheckedAt.identifier(),
|
SessionColumnPasswordCheckedAt.identifier(),
|
||||||
SessionColumnIntentCheckedAt.identifier(),
|
SessionColumnIntentCheckedAt.identifier(),
|
||||||
SessionColumnWebAuthNCheckedAt.identifier(),
|
SessionColumnWebAuthNCheckedAt.identifier(),
|
||||||
@ -426,10 +430,10 @@ func prepareSessionsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBui
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
userID sql.NullString
|
userID sql.NullString
|
||||||
|
userResourceOwner sql.NullString
|
||||||
userCheckedAt sql.NullTime
|
userCheckedAt sql.NullTime
|
||||||
loginName sql.NullString
|
loginName sql.NullString
|
||||||
displayName sql.NullString
|
displayName sql.NullString
|
||||||
userResourceOwner sql.NullString
|
|
||||||
passwordCheckedAt sql.NullTime
|
passwordCheckedAt sql.NullTime
|
||||||
intentCheckedAt sql.NullTime
|
intentCheckedAt sql.NullTime
|
||||||
webAuthNCheckedAt sql.NullTime
|
webAuthNCheckedAt sql.NullTime
|
||||||
@ -450,10 +454,10 @@ func prepareSessionsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBui
|
|||||||
&session.ResourceOwner,
|
&session.ResourceOwner,
|
||||||
&session.Creator,
|
&session.Creator,
|
||||||
&userID,
|
&userID,
|
||||||
|
&userResourceOwner,
|
||||||
&userCheckedAt,
|
&userCheckedAt,
|
||||||
&loginName,
|
&loginName,
|
||||||
&displayName,
|
&displayName,
|
||||||
&userResourceOwner,
|
|
||||||
&passwordCheckedAt,
|
&passwordCheckedAt,
|
||||||
&intentCheckedAt,
|
&intentCheckedAt,
|
||||||
&webAuthNCheckedAt,
|
&webAuthNCheckedAt,
|
||||||
@ -470,10 +474,10 @@ func prepareSessionsQuery(ctx context.Context, db prepareDatabase) (sq.SelectBui
|
|||||||
return nil, errors.ThrowInternal(err, "QUERY-SAfeg", "Errors.Internal")
|
return nil, errors.ThrowInternal(err, "QUERY-SAfeg", "Errors.Internal")
|
||||||
}
|
}
|
||||||
session.UserFactor.UserID = userID.String
|
session.UserFactor.UserID = userID.String
|
||||||
|
session.UserFactor.ResourceOwner = userResourceOwner.String
|
||||||
session.UserFactor.UserCheckedAt = userCheckedAt.Time
|
session.UserFactor.UserCheckedAt = userCheckedAt.Time
|
||||||
session.UserFactor.LoginName = loginName.String
|
session.UserFactor.LoginName = loginName.String
|
||||||
session.UserFactor.DisplayName = displayName.String
|
session.UserFactor.DisplayName = displayName.String
|
||||||
session.UserFactor.ResourceOwner = userResourceOwner.String
|
|
||||||
session.PasswordFactor.PasswordCheckedAt = passwordCheckedAt.Time
|
session.PasswordFactor.PasswordCheckedAt = passwordCheckedAt.Time
|
||||||
session.IntentFactor.IntentCheckedAt = intentCheckedAt.Time
|
session.IntentFactor.IntentCheckedAt = intentCheckedAt.Time
|
||||||
session.WebAuthNFactor.WebAuthNCheckedAt = webAuthNCheckedAt.Time
|
session.WebAuthNFactor.WebAuthNCheckedAt = webAuthNCheckedAt.Time
|
||||||
|
@ -20,63 +20,63 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
expectedSessionQuery = regexp.QuoteMeta(`SELECT projections.sessions7.id,` +
|
expectedSessionQuery = regexp.QuoteMeta(`SELECT projections.sessions8.id,` +
|
||||||
` projections.sessions7.creation_date,` +
|
` projections.sessions8.creation_date,` +
|
||||||
` projections.sessions7.change_date,` +
|
` projections.sessions8.change_date,` +
|
||||||
` projections.sessions7.sequence,` +
|
` projections.sessions8.sequence,` +
|
||||||
` projections.sessions7.state,` +
|
` projections.sessions8.state,` +
|
||||||
` projections.sessions7.resource_owner,` +
|
` projections.sessions8.resource_owner,` +
|
||||||
` projections.sessions7.creator,` +
|
` projections.sessions8.creator,` +
|
||||||
` projections.sessions7.user_id,` +
|
` projections.sessions8.user_id,` +
|
||||||
` projections.sessions7.user_checked_at,` +
|
` projections.sessions8.user_resource_owner,` +
|
||||||
|
` projections.sessions8.user_checked_at,` +
|
||||||
` projections.login_names2.login_name,` +
|
` projections.login_names2.login_name,` +
|
||||||
` projections.users8_humans.display_name,` +
|
` projections.users8_humans.display_name,` +
|
||||||
` projections.users8.resource_owner,` +
|
` projections.sessions8.password_checked_at,` +
|
||||||
` projections.sessions7.password_checked_at,` +
|
` projections.sessions8.intent_checked_at,` +
|
||||||
` projections.sessions7.intent_checked_at,` +
|
` projections.sessions8.webauthn_checked_at,` +
|
||||||
` projections.sessions7.webauthn_checked_at,` +
|
` projections.sessions8.webauthn_user_verified,` +
|
||||||
` projections.sessions7.webauthn_user_verified,` +
|
` projections.sessions8.totp_checked_at,` +
|
||||||
` projections.sessions7.totp_checked_at,` +
|
` projections.sessions8.otp_sms_checked_at,` +
|
||||||
` projections.sessions7.otp_sms_checked_at,` +
|
` projections.sessions8.otp_email_checked_at,` +
|
||||||
` projections.sessions7.otp_email_checked_at,` +
|
` projections.sessions8.metadata,` +
|
||||||
` projections.sessions7.metadata,` +
|
` projections.sessions8.token_id,` +
|
||||||
` projections.sessions7.token_id,` +
|
` projections.sessions8.user_agent_fingerprint_id,` +
|
||||||
` projections.sessions7.user_agent_fingerprint_id,` +
|
` projections.sessions8.user_agent_ip,` +
|
||||||
` projections.sessions7.user_agent_ip,` +
|
` projections.sessions8.user_agent_description,` +
|
||||||
` projections.sessions7.user_agent_description,` +
|
` projections.sessions8.user_agent_header,` +
|
||||||
` projections.sessions7.user_agent_header,` +
|
` projections.sessions8.expiration` +
|
||||||
` projections.sessions7.expiration` +
|
` FROM projections.sessions8` +
|
||||||
` FROM projections.sessions7` +
|
` LEFT JOIN projections.login_names2 ON projections.sessions8.user_id = projections.login_names2.user_id AND projections.sessions8.instance_id = projections.login_names2.instance_id` +
|
||||||
` LEFT JOIN projections.login_names2 ON projections.sessions7.user_id = projections.login_names2.user_id AND projections.sessions7.instance_id = projections.login_names2.instance_id` +
|
` LEFT JOIN projections.users8_humans ON projections.sessions8.user_id = projections.users8_humans.user_id AND projections.sessions8.instance_id = projections.users8_humans.instance_id` +
|
||||||
` LEFT JOIN projections.users8_humans ON projections.sessions7.user_id = projections.users8_humans.user_id AND projections.sessions7.instance_id = projections.users8_humans.instance_id` +
|
` LEFT JOIN projections.users8 ON projections.sessions8.user_id = projections.users8.id AND projections.sessions8.instance_id = projections.users8.instance_id` +
|
||||||
` LEFT JOIN projections.users8 ON projections.sessions7.user_id = projections.users8.id AND projections.sessions7.instance_id = projections.users8.instance_id` +
|
|
||||||
` AS OF SYSTEM TIME '-1 ms'`)
|
` AS OF SYSTEM TIME '-1 ms'`)
|
||||||
expectedSessionsQuery = regexp.QuoteMeta(`SELECT projections.sessions7.id,` +
|
expectedSessionsQuery = regexp.QuoteMeta(`SELECT projections.sessions8.id,` +
|
||||||
` projections.sessions7.creation_date,` +
|
` projections.sessions8.creation_date,` +
|
||||||
` projections.sessions7.change_date,` +
|
` projections.sessions8.change_date,` +
|
||||||
` projections.sessions7.sequence,` +
|
` projections.sessions8.sequence,` +
|
||||||
` projections.sessions7.state,` +
|
` projections.sessions8.state,` +
|
||||||
` projections.sessions7.resource_owner,` +
|
` projections.sessions8.resource_owner,` +
|
||||||
` projections.sessions7.creator,` +
|
` projections.sessions8.creator,` +
|
||||||
` projections.sessions7.user_id,` +
|
` projections.sessions8.user_id,` +
|
||||||
` projections.sessions7.user_checked_at,` +
|
` projections.sessions8.user_resource_owner,` +
|
||||||
|
` projections.sessions8.user_checked_at,` +
|
||||||
` projections.login_names2.login_name,` +
|
` projections.login_names2.login_name,` +
|
||||||
` projections.users8_humans.display_name,` +
|
` projections.users8_humans.display_name,` +
|
||||||
` projections.users8.resource_owner,` +
|
` projections.sessions8.password_checked_at,` +
|
||||||
` projections.sessions7.password_checked_at,` +
|
` projections.sessions8.intent_checked_at,` +
|
||||||
` projections.sessions7.intent_checked_at,` +
|
` projections.sessions8.webauthn_checked_at,` +
|
||||||
` projections.sessions7.webauthn_checked_at,` +
|
` projections.sessions8.webauthn_user_verified,` +
|
||||||
` projections.sessions7.webauthn_user_verified,` +
|
` projections.sessions8.totp_checked_at,` +
|
||||||
` projections.sessions7.totp_checked_at,` +
|
` projections.sessions8.otp_sms_checked_at,` +
|
||||||
` projections.sessions7.otp_sms_checked_at,` +
|
` projections.sessions8.otp_email_checked_at,` +
|
||||||
` projections.sessions7.otp_email_checked_at,` +
|
` projections.sessions8.metadata,` +
|
||||||
` projections.sessions7.metadata,` +
|
` projections.sessions8.expiration,` +
|
||||||
` projections.sessions7.expiration,` +
|
|
||||||
` COUNT(*) OVER ()` +
|
` COUNT(*) OVER ()` +
|
||||||
` FROM projections.sessions7` +
|
` FROM projections.sessions8` +
|
||||||
` LEFT JOIN projections.login_names2 ON projections.sessions7.user_id = projections.login_names2.user_id AND projections.sessions7.instance_id = projections.login_names2.instance_id` +
|
` LEFT JOIN projections.login_names2 ON projections.sessions8.user_id = projections.login_names2.user_id AND projections.sessions8.instance_id = projections.login_names2.instance_id` +
|
||||||
` LEFT JOIN projections.users8_humans ON projections.sessions7.user_id = projections.users8_humans.user_id AND projections.sessions7.instance_id = projections.users8_humans.instance_id` +
|
` LEFT JOIN projections.users8_humans ON projections.sessions8.user_id = projections.users8_humans.user_id AND projections.sessions8.instance_id = projections.users8_humans.instance_id` +
|
||||||
` LEFT JOIN projections.users8 ON projections.sessions7.user_id = projections.users8.id AND projections.sessions7.instance_id = projections.users8.instance_id` +
|
` LEFT JOIN projections.users8 ON projections.sessions8.user_id = projections.users8.id AND projections.sessions8.instance_id = projections.users8.instance_id` +
|
||||||
` AS OF SYSTEM TIME '-1 ms'`)
|
` AS OF SYSTEM TIME '-1 ms'`)
|
||||||
|
|
||||||
sessionCols = []string{
|
sessionCols = []string{
|
||||||
@ -88,10 +88,10 @@ var (
|
|||||||
"resource_owner",
|
"resource_owner",
|
||||||
"creator",
|
"creator",
|
||||||
"user_id",
|
"user_id",
|
||||||
|
"user_resource_owner",
|
||||||
"user_checked_at",
|
"user_checked_at",
|
||||||
"login_name",
|
"login_name",
|
||||||
"display_name",
|
"display_name",
|
||||||
"user_resource_owner",
|
|
||||||
"password_checked_at",
|
"password_checked_at",
|
||||||
"intent_checked_at",
|
"intent_checked_at",
|
||||||
"webauthn_checked_at",
|
"webauthn_checked_at",
|
||||||
@ -117,10 +117,10 @@ var (
|
|||||||
"resource_owner",
|
"resource_owner",
|
||||||
"creator",
|
"creator",
|
||||||
"user_id",
|
"user_id",
|
||||||
|
"user_resource_owner",
|
||||||
"user_checked_at",
|
"user_checked_at",
|
||||||
"login_name",
|
"login_name",
|
||||||
"display_name",
|
"display_name",
|
||||||
"user_resource_owner",
|
|
||||||
"password_checked_at",
|
"password_checked_at",
|
||||||
"intent_checked_at",
|
"intent_checked_at",
|
||||||
"webauthn_checked_at",
|
"webauthn_checked_at",
|
||||||
@ -174,10 +174,10 @@ func Test_SessionsPrepare(t *testing.T) {
|
|||||||
"ro",
|
"ro",
|
||||||
"creator",
|
"creator",
|
||||||
"user-id",
|
"user-id",
|
||||||
|
"resourceOwner",
|
||||||
testNow,
|
testNow,
|
||||||
"login-name",
|
"login-name",
|
||||||
"display-name",
|
"display-name",
|
||||||
"resourceOwner",
|
|
||||||
testNow,
|
testNow,
|
||||||
testNow,
|
testNow,
|
||||||
testNow,
|
testNow,
|
||||||
@ -255,10 +255,10 @@ func Test_SessionsPrepare(t *testing.T) {
|
|||||||
"ro",
|
"ro",
|
||||||
"creator",
|
"creator",
|
||||||
"user-id",
|
"user-id",
|
||||||
|
"resourceOwner",
|
||||||
testNow,
|
testNow,
|
||||||
"login-name",
|
"login-name",
|
||||||
"display-name",
|
"display-name",
|
||||||
"resourceOwner",
|
|
||||||
testNow,
|
testNow,
|
||||||
testNow,
|
testNow,
|
||||||
testNow,
|
testNow,
|
||||||
@ -278,10 +278,10 @@ func Test_SessionsPrepare(t *testing.T) {
|
|||||||
"ro",
|
"ro",
|
||||||
"creator2",
|
"creator2",
|
||||||
"user-id2",
|
"user-id2",
|
||||||
|
"resourceOwner",
|
||||||
testNow,
|
testNow,
|
||||||
"login-name2",
|
"login-name2",
|
||||||
"display-name2",
|
"display-name2",
|
||||||
"resourceOwner",
|
|
||||||
testNow,
|
testNow,
|
||||||
testNow,
|
testNow,
|
||||||
testNow,
|
testNow,
|
||||||
@ -451,10 +451,10 @@ func Test_SessionPrepare(t *testing.T) {
|
|||||||
"ro",
|
"ro",
|
||||||
"creator",
|
"creator",
|
||||||
"user-id",
|
"user-id",
|
||||||
|
"resourceOwner",
|
||||||
testNow,
|
testNow,
|
||||||
"login-name",
|
"login-name",
|
||||||
"display-name",
|
"display-name",
|
||||||
"resourceOwner",
|
|
||||||
testNow,
|
testNow,
|
||||||
testNow,
|
testNow,
|
||||||
testNow,
|
testNow,
|
||||||
|
@ -75,8 +75,9 @@ func AddedEventMapper(event eventstore.Event) (eventstore.Event, error) {
|
|||||||
type UserCheckedEvent struct {
|
type UserCheckedEvent struct {
|
||||||
eventstore.BaseEvent `json:"-"`
|
eventstore.BaseEvent `json:"-"`
|
||||||
|
|
||||||
UserID string `json:"userID"`
|
UserID string `json:"userID"`
|
||||||
CheckedAt time.Time `json:"checkedAt"`
|
UserResourceOwner string `json:"userResourceOwner"`
|
||||||
|
CheckedAt time.Time `json:"checkedAt"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *UserCheckedEvent) Payload() interface{} {
|
func (e *UserCheckedEvent) Payload() interface{} {
|
||||||
@ -90,7 +91,8 @@ func (e *UserCheckedEvent) UniqueConstraints() []*eventstore.UniqueConstraint {
|
|||||||
func NewUserCheckedEvent(
|
func NewUserCheckedEvent(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
aggregate *eventstore.Aggregate,
|
aggregate *eventstore.Aggregate,
|
||||||
userID string,
|
userID,
|
||||||
|
userResourceOwner string,
|
||||||
checkedAt time.Time,
|
checkedAt time.Time,
|
||||||
) *UserCheckedEvent {
|
) *UserCheckedEvent {
|
||||||
return &UserCheckedEvent{
|
return &UserCheckedEvent{
|
||||||
@ -99,8 +101,9 @@ func NewUserCheckedEvent(
|
|||||||
aggregate,
|
aggregate,
|
||||||
UserCheckedType,
|
UserCheckedType,
|
||||||
),
|
),
|
||||||
UserID: userID,
|
UserID: userID,
|
||||||
CheckedAt: checkedAt,
|
UserResourceOwner: userResourceOwner,
|
||||||
|
CheckedAt: checkedAt,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,12 +290,12 @@ message CreateSessionResponse{
|
|||||||
string session_id = 2 [
|
string session_id = 2 [
|
||||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||||
description: "\"id of the session\"";
|
description: "\"id of the session\"";
|
||||||
example: "\"d654e6ba-70a3-48ef-a95d-37c8d8a7901a\"";
|
example: "\"222430354126975533\"";
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
string session_token = 3 [
|
string session_token = 3 [
|
||||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||||
description: "\"token of the session, which is required for further updates of the session or the request other resources\"";
|
description: "\"The current token of the session, which is required for further updates of the session or the request other resources.\"";
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
Challenges challenges = 4;
|
Challenges challenges = 4;
|
||||||
@ -308,7 +308,7 @@ message SetSessionRequest{
|
|||||||
min_length: 1;
|
min_length: 1;
|
||||||
max_length: 200;
|
max_length: 200;
|
||||||
description: "\"id of the session to update\"";
|
description: "\"id of the session to update\"";
|
||||||
example: "\"d654e6ba-70a3-48ef-a95d-37c8d8a7901a\"";
|
example: "\"222430354126975533\"";
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
string session_token = 2 [
|
string session_token = 2 [
|
||||||
@ -316,7 +316,7 @@ message SetSessionRequest{
|
|||||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||||
min_length: 1;
|
min_length: 1;
|
||||||
max_length: 200;
|
max_length: 200;
|
||||||
description: "\"token of the session, previously returned on the create / update request\"";
|
description: "\"The current token of the session, previously returned on the create / update request.\"";
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
Checks checks = 3[
|
Checks checks = 3[
|
||||||
@ -342,7 +342,7 @@ message SetSessionResponse{
|
|||||||
zitadel.object.v2beta.Details details = 1;
|
zitadel.object.v2beta.Details details = 1;
|
||||||
string session_token = 2 [
|
string session_token = 2 [
|
||||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||||
description: "\"token of the session, which is required for further updates of the session or the request other resources\"";
|
description: "\"The current token of the session, which is required for further updates of the session or to request other resources.\"";
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
Challenges challenges = 3;
|
Challenges challenges = 3;
|
||||||
@ -355,12 +355,12 @@ message DeleteSessionRequest{
|
|||||||
min_length: 1;
|
min_length: 1;
|
||||||
max_length: 200;
|
max_length: 200;
|
||||||
description: "\"id of the session to terminate\"";
|
description: "\"id of the session to terminate\"";
|
||||||
example: "\"d654e6ba-70a3-48ef-a95d-37c8d8a7901a\"";
|
example: "\"222430354126975533\"";
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
optional string session_token = 2 [
|
optional string session_token = 2 [
|
||||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||||
description: "\"token of the session, previously returned on the create / update request\"";
|
description: "\"The current token of the session, previously returned on the create / update request. The token is required unless the authenticated user terminates the own session or is granted the `session.delete` permission.\"";
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user