mirror of
https://github.com/andwati/zitadel.git
synced 2026-10-18 05:52:51 +00:00
# Which Problems Are Solved - The eventstore did not support intentionally overwriting the resource owner when creating events for aggregates that may be reused across owners. - Resource owner handling was implicit and could not be controlled per command/event type. - We needed a safe way to distinguish between: - keeping the existing aggregate owner, and - explicitly setting a new owner for specific create-like events. # How the Problems Are Solved - Introduced a new eventstore command type with an explicit enforce_owner flag. - Updated eventstore.commands_to_events and eventstore.push so owner assignment is now explicit: - if enforce_owner is true, the command owner is written - if enforce_owner is false, the existing aggregate owner is retained when present - Added EnforceResourceOwnerCommand and wiring so command types can opt in to enforced owner behavior. - Wired the new behavior through the v3 eventstore push path, including compatibility fallback for older command type mapping. - Added migration/setup changes to register and use the new command type and SQL functions. - Added and updated tests for owner overwrite and aggregate ID reuse scenarios. # Additional Changes - Added small migration/setup robustness improvements related to eventstore setup ordering and helper reuse. - Added focused test coverage for enforced owner behavior and sequencing. - Events that currently allow owner changes (implement EnforceResourceOwner) are: - AddedEvent (action) - GroupAddedEvent - StartedEvent (idp intent) - ProjectAddedEvent - HumanAddedEvent - HumanRegisteredEvent - MachineAddedEvent - CreatedEvent (schema user) # Additional Context - Follow-up for eventstore owner-handling correctness in create flows and aggregate ID reuse cases. - No additional issue link was attached for this change. --------- Co-authored-by: abhishek kumar gupta <[email protected]>
95 lines
2.2 KiB
Go
95 lines
2.2 KiB
Go
package eventstore
|
|
|
|
import (
|
|
"github.com/zitadel/zitadel/internal/eventstore"
|
|
)
|
|
|
|
var _ eventstore.Command = (*mockCommand)(nil)
|
|
var _ eventstore.EnforceResourceOwnerCommand = (*enforcedMockCommand)(nil)
|
|
|
|
type mockCommand struct {
|
|
aggregate *eventstore.Aggregate
|
|
payload any
|
|
constraints []*eventstore.UniqueConstraint
|
|
}
|
|
|
|
type enforcedMockCommand struct {
|
|
*mockCommand
|
|
}
|
|
|
|
func (*enforcedMockCommand) EnforceResourceOwner() {}
|
|
|
|
// Aggregate implements [eventstore.Command]
|
|
func (m *mockCommand) Aggregate() *eventstore.Aggregate {
|
|
return m.aggregate
|
|
}
|
|
|
|
// Creator implements [eventstore.Command]
|
|
func (m *mockCommand) Creator() string {
|
|
return "creator"
|
|
}
|
|
|
|
// Revision implements [eventstore.Command]
|
|
func (m *mockCommand) Revision() uint16 {
|
|
return 1
|
|
}
|
|
|
|
// Type implements [eventstore.Command]
|
|
func (m *mockCommand) Type() eventstore.EventType {
|
|
return "event.type"
|
|
}
|
|
|
|
// Payload implements [eventstore.Command]
|
|
func (m *mockCommand) Payload() any {
|
|
return m.payload
|
|
}
|
|
|
|
// UniqueConstraints implements [eventstore.Command]
|
|
func (m *mockCommand) UniqueConstraints() []*eventstore.UniqueConstraint {
|
|
return m.constraints
|
|
}
|
|
|
|
func (e *mockCommand) Fields() []*eventstore.FieldOperation {
|
|
return nil
|
|
}
|
|
|
|
func mockEvent(aggregate *eventstore.Aggregate, sequence uint64, payload Payload) eventstore.Event {
|
|
return mockEventType(aggregate, sequence, payload, "event.type")
|
|
}
|
|
|
|
func mockEventType(aggregate *eventstore.Aggregate, sequence uint64, payload Payload, typ string) eventstore.Event {
|
|
return &event{
|
|
command: &command{
|
|
InstanceID: aggregate.InstanceID,
|
|
AggregateType: string(aggregate.Type),
|
|
AggregateID: aggregate.ID,
|
|
Owner: aggregate.ResourceOwner,
|
|
Creator: "creator",
|
|
Revision: 1,
|
|
CommandType: typ,
|
|
Payload: payload,
|
|
},
|
|
sequence: sequence,
|
|
}
|
|
}
|
|
|
|
func mockAggregate(id string) *eventstore.Aggregate {
|
|
return &eventstore.Aggregate{
|
|
ID: id,
|
|
Type: "type",
|
|
ResourceOwner: "ro",
|
|
InstanceID: "instance",
|
|
Version: "v1",
|
|
}
|
|
}
|
|
|
|
func mockAggregateWithInstance(id, instance string) *eventstore.Aggregate {
|
|
return &eventstore.Aggregate{
|
|
ID: id,
|
|
InstanceID: instance,
|
|
Type: "type",
|
|
ResourceOwner: "ro",
|
|
Version: "v1",
|
|
}
|
|
}
|