mirror of
https://github.com/zitadel/zitadel.git
synced 2025-03-04 09:55:14 +00:00
fix: correctly delete sessions created before 2.42 (#7050)
* fix: correctly delete sessions created before 2.42 * fix test * fix linting * fixes requested from review
This commit is contained in:
parent
aa3c352ae7
commit
831bb88ec4
41
internal/command/resource_ower_model.go
Normal file
41
internal/command/resource_ower_model.go
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/zitadel/zitadel/internal/eventstore"
|
||||||
|
)
|
||||||
|
|
||||||
|
// resourceOwnerModel can be used to retrieve the resourceOwner of an aggregate
|
||||||
|
// by checking the first event it.
|
||||||
|
type resourceOwnerModel struct {
|
||||||
|
instanceID string
|
||||||
|
aggregateType eventstore.AggregateType
|
||||||
|
aggregateID string
|
||||||
|
|
||||||
|
resourceOwner string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewResourceOwnerModel(instanceID string, aggregateType eventstore.AggregateType, aggregateID string) *resourceOwnerModel {
|
||||||
|
return &resourceOwnerModel{
|
||||||
|
instanceID: instanceID,
|
||||||
|
aggregateType: aggregateType,
|
||||||
|
aggregateID: aggregateID,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *resourceOwnerModel) Reduce() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (r *resourceOwnerModel) AppendEvents(events ...eventstore.Event) {
|
||||||
|
if len(events) == 1 {
|
||||||
|
r.resourceOwner = events[0].Aggregate().ResourceOwner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (r *resourceOwnerModel) Query() *eventstore.SearchQueryBuilder {
|
||||||
|
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
|
||||||
|
InstanceID(r.instanceID).
|
||||||
|
AddQuery().
|
||||||
|
AggregateTypes(r.aggregateType).
|
||||||
|
AggregateIDs(r.aggregateID).
|
||||||
|
Builder().
|
||||||
|
Limit(1)
|
||||||
|
}
|
@ -400,7 +400,27 @@ func (c *Commands) checkSessionTerminationPermission(ctx context.Context, model
|
|||||||
if model.UserID != "" && model.UserID == authz.GetCtxData(ctx).UserID {
|
if model.UserID != "" && model.UserID == authz.GetCtxData(ctx).UserID {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return c.checkPermission(ctx, domain.PermissionSessionDelete, model.UserResourceOwner, model.UserID)
|
userResourceOwner, err := c.sessionUserResourceOwner(ctx, model)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return c.checkPermission(ctx, domain.PermissionSessionDelete, userResourceOwner, model.UserID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// sessionUserResourceOwner will return the resourceOwner of the session form the [SessionWriteModel] or by additionally calling the eventstore,
|
||||||
|
// because before 2.42.0, the resourceOwner of a session used to be the organisation of the creator.
|
||||||
|
// Further the (checked) users organisation id was not stored.
|
||||||
|
// To be able to check the permission, we need to get the user's resourceOwner in this case.
|
||||||
|
func (c *Commands) sessionUserResourceOwner(ctx context.Context, model *SessionWriteModel) (string, error) {
|
||||||
|
if model.UserID == "" || model.UserResourceOwner != "" {
|
||||||
|
return model.UserResourceOwner, nil
|
||||||
|
}
|
||||||
|
r := NewResourceOwnerModel(authz.GetInstance(ctx).InstanceID(), user.AggregateType, model.UserID)
|
||||||
|
err := c.eventstore.FilterToQueryReducer(ctx, r)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return r.resourceOwner, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
|
@ -63,7 +63,6 @@ func NewSessionWriteModel(sessionID string, instanceID string) *SessionWriteMode
|
|||||||
return &SessionWriteModel{
|
return &SessionWriteModel{
|
||||||
WriteModel: eventstore.WriteModel{
|
WriteModel: eventstore.WriteModel{
|
||||||
AggregateID: sessionID,
|
AggregateID: sessionID,
|
||||||
ResourceOwner: instanceID,
|
|
||||||
},
|
},
|
||||||
Metadata: make(map[string][]byte),
|
Metadata: make(map[string][]byte),
|
||||||
aggregate: &session.NewAggregate(sessionID, instanceID).Aggregate,
|
aggregate: &session.NewAggregate(sessionID, instanceID).Aggregate,
|
||||||
|
@ -487,9 +487,7 @@ func TestCommands_updateSession(t *testing.T) {
|
|||||||
},
|
},
|
||||||
res{
|
res{
|
||||||
want: &SessionChanged{
|
want: &SessionChanged{
|
||||||
ObjectDetails: &domain.ObjectDetails{
|
ObjectDetails: &domain.ObjectDetails{},
|
||||||
ResourceOwner: "instance1",
|
|
||||||
},
|
|
||||||
ID: "sessionID",
|
ID: "sessionID",
|
||||||
NewToken: "",
|
NewToken: "",
|
||||||
},
|
},
|
||||||
@ -1251,6 +1249,52 @@ func TestCommands_TerminateSession(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"terminate session owned by org 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", "org2").Aggregate,
|
||||||
|
"userID", "", testNow),
|
||||||
|
),
|
||||||
|
eventFromEventPusher(
|
||||||
|
session.NewTokenSetEvent(context.Background(), &session.NewAggregate("sessionID", "org2").Aggregate,
|
||||||
|
"tokenID"),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
expectFilter(
|
||||||
|
user.NewHumanAddedEvent(context.Background(), &user.NewAggregate("userID", "org1").Aggregate,
|
||||||
|
"username", "firstname", "lastname", "nickname", "displayname", language.English, domain.GenderUnspecified, "email", false),
|
||||||
|
),
|
||||||
|
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",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user