2023-10-19 10:19:10 +00:00
|
|
|
package eventstore
|
|
|
|
|
|
|
|
import (
|
2024-12-04 13:51:40 +00:00
|
|
|
"context"
|
2023-10-19 10:19:10 +00:00
|
|
|
"encoding/json"
|
2024-12-04 13:51:40 +00:00
|
|
|
"strconv"
|
2023-10-19 10:19:10 +00:00
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/zitadel/logging"
|
2024-12-04 13:51:40 +00:00
|
|
|
"github.com/zitadel/zitadel/internal/api/authz"
|
2023-10-19 10:19:10 +00:00
|
|
|
"github.com/zitadel/zitadel/internal/eventstore"
|
2023-12-08 14:30:55 +00:00
|
|
|
"github.com/zitadel/zitadel/internal/zerrors"
|
2023-10-19 10:19:10 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
_ eventstore.Event = (*event)(nil)
|
|
|
|
)
|
|
|
|
|
2024-12-04 13:51:40 +00:00
|
|
|
type command struct {
|
|
|
|
InstanceID string
|
|
|
|
AggregateType string
|
|
|
|
AggregateID string
|
|
|
|
CommandType string
|
|
|
|
Revision uint16
|
|
|
|
Payload Payload
|
|
|
|
Creator string
|
|
|
|
Owner string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *command) Aggregate() *eventstore.Aggregate {
|
|
|
|
return &eventstore.Aggregate{
|
|
|
|
ID: c.AggregateID,
|
|
|
|
Type: eventstore.AggregateType(c.AggregateType),
|
|
|
|
ResourceOwner: c.Owner,
|
|
|
|
InstanceID: c.InstanceID,
|
|
|
|
Version: eventstore.Version("v" + strconv.Itoa(int(c.Revision))),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-19 10:19:10 +00:00
|
|
|
type event struct {
|
2024-12-04 13:51:40 +00:00
|
|
|
command *command
|
2023-10-19 10:19:10 +00:00
|
|
|
createdAt time.Time
|
|
|
|
sequence uint64
|
2024-09-24 16:43:29 +00:00
|
|
|
position float64
|
2023-10-19 10:19:10 +00:00
|
|
|
}
|
|
|
|
|
2024-12-04 13:51:40 +00:00
|
|
|
// TODO: remove on v3
|
|
|
|
func commandToEventOld(sequence *latestSequence, cmd eventstore.Command) (_ *event, err error) {
|
2023-10-19 10:19:10 +00:00
|
|
|
var payload Payload
|
2024-12-04 13:51:40 +00:00
|
|
|
if cmd.Payload() != nil {
|
|
|
|
payload, err = json.Marshal(cmd.Payload())
|
2023-10-19 10:19:10 +00:00
|
|
|
if err != nil {
|
|
|
|
logging.WithError(err).Warn("marshal payload failed")
|
2023-12-08 14:30:55 +00:00
|
|
|
return nil, zerrors.ThrowInternal(err, "V3-MInPK", "Errors.Internal")
|
2023-10-19 10:19:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return &event{
|
2024-12-04 13:51:40 +00:00
|
|
|
command: &command{
|
|
|
|
InstanceID: sequence.aggregate.InstanceID,
|
|
|
|
AggregateType: string(sequence.aggregate.Type),
|
|
|
|
AggregateID: sequence.aggregate.ID,
|
|
|
|
CommandType: string(cmd.Type()),
|
|
|
|
Revision: cmd.Revision(),
|
|
|
|
Payload: payload,
|
|
|
|
Creator: cmd.Creator(),
|
|
|
|
Owner: sequence.aggregate.ResourceOwner,
|
|
|
|
},
|
|
|
|
sequence: sequence.sequence,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func commandsToEvents(ctx context.Context, cmds []eventstore.Command) (_ []eventstore.Event, _ []*command, err error) {
|
|
|
|
events := make([]eventstore.Event, len(cmds))
|
|
|
|
commands := make([]*command, len(cmds))
|
|
|
|
for i, cmd := range cmds {
|
|
|
|
if cmd.Aggregate().InstanceID == "" {
|
|
|
|
cmd.Aggregate().InstanceID = authz.GetInstance(ctx).InstanceID()
|
|
|
|
}
|
|
|
|
events[i], err = commandToEvent(cmd)
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
commands[i] = events[i].(*event).command
|
|
|
|
}
|
|
|
|
return events, commands, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func commandToEvent(cmd eventstore.Command) (_ eventstore.Event, err error) {
|
|
|
|
var payload Payload
|
|
|
|
if cmd.Payload() != nil {
|
|
|
|
payload, err = json.Marshal(cmd.Payload())
|
|
|
|
if err != nil {
|
|
|
|
logging.WithError(err).Warn("marshal payload failed")
|
|
|
|
return nil, zerrors.ThrowInternal(err, "V3-MInPK", "Errors.Internal")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
command := &command{
|
|
|
|
InstanceID: cmd.Aggregate().InstanceID,
|
|
|
|
AggregateType: string(cmd.Aggregate().Type),
|
|
|
|
AggregateID: cmd.Aggregate().ID,
|
|
|
|
CommandType: string(cmd.Type()),
|
|
|
|
Revision: cmd.Revision(),
|
|
|
|
Payload: payload,
|
|
|
|
Creator: cmd.Creator(),
|
|
|
|
Owner: cmd.Aggregate().ResourceOwner,
|
|
|
|
}
|
|
|
|
|
|
|
|
return &event{
|
|
|
|
command: command,
|
2023-10-19 10:19:10 +00:00
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// CreationDate implements [eventstore.Event]
|
|
|
|
func (e *event) CreationDate() time.Time {
|
|
|
|
return e.CreatedAt()
|
|
|
|
}
|
|
|
|
|
|
|
|
// EditorUser implements [eventstore.Event]
|
|
|
|
func (e *event) EditorUser() string {
|
|
|
|
return e.Creator()
|
|
|
|
}
|
|
|
|
|
|
|
|
// Aggregate implements [eventstore.Event]
|
|
|
|
func (e *event) Aggregate() *eventstore.Aggregate {
|
2024-12-04 13:51:40 +00:00
|
|
|
return e.command.Aggregate()
|
2023-10-19 10:19:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Creator implements [eventstore.Event]
|
|
|
|
func (e *event) Creator() string {
|
2024-12-04 13:51:40 +00:00
|
|
|
return e.command.Creator
|
2023-10-19 10:19:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Revision implements [eventstore.Event]
|
|
|
|
func (e *event) Revision() uint16 {
|
2024-12-04 13:51:40 +00:00
|
|
|
return e.command.Revision
|
2023-10-19 10:19:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Type implements [eventstore.Event]
|
|
|
|
func (e *event) Type() eventstore.EventType {
|
2024-12-04 13:51:40 +00:00
|
|
|
return eventstore.EventType(e.command.CommandType)
|
2023-10-19 10:19:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// CreatedAt implements [eventstore.Event]
|
|
|
|
func (e *event) CreatedAt() time.Time {
|
|
|
|
return e.createdAt
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sequence implements [eventstore.Event]
|
|
|
|
func (e *event) Sequence() uint64 {
|
|
|
|
return e.sequence
|
|
|
|
}
|
|
|
|
|
2024-09-24 16:43:29 +00:00
|
|
|
// Sequence implements [eventstore.Event]
|
|
|
|
func (e *event) Position() float64 {
|
2023-10-19 10:19:10 +00:00
|
|
|
return e.position
|
|
|
|
}
|
|
|
|
|
|
|
|
// Unmarshal implements [eventstore.Event]
|
|
|
|
func (e *event) Unmarshal(ptr any) error {
|
2024-12-04 13:51:40 +00:00
|
|
|
if len(e.command.Payload) == 0 {
|
2023-10-19 10:19:10 +00:00
|
|
|
return nil
|
|
|
|
}
|
2024-12-04 13:51:40 +00:00
|
|
|
if err := json.Unmarshal(e.command.Payload, ptr); err != nil {
|
2023-12-08 14:30:55 +00:00
|
|
|
return zerrors.ThrowInternal(err, "V3-u8qVo", "Errors.Internal")
|
2023-10-19 10:19:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// DataAsBytes implements [eventstore.Event]
|
|
|
|
func (e *event) DataAsBytes() []byte {
|
2024-12-04 13:51:40 +00:00
|
|
|
return e.command.Payload
|
2023-10-19 10:19:10 +00:00
|
|
|
}
|